diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f0c5c62cbe6b..000000000000 --- a/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -*.a -*.core -*.o -*.orig -*.rej -*.so -*.sw[nop] -*~ -_.tinderbox.* -_.universe-toolchain -_.amd64.* -_.arm.* -_.arm64.* -_.i386.* -_.ia64.* -_.mips.* -_.pc98.* -_.powerpc.* -_.riscv.* -_.sparc64.* -_.sun4v.* -GPATH -GRTAGS -GTAGS -ID -cscope.files -cscope.in.out -cscope.out -cscope.po.out -compile_commands.json -tags -.clangd -.ccls-cache diff --git a/contrib/byacc/test/btyacc/err_syntax22.error b/contrib/byacc/test/btyacc/err_syntax22.error deleted file mode 100644 index 8622aa73f598..000000000000 --- a/contrib/byacc/test/btyacc/err_syntax22.error +++ /dev/null @@ -1 +0,0 @@ -YACC: e - line 17 of "./err_syntax22.y", $2 (recur) is untyped diff --git a/contrib/byacc/test/yacc/err_syntax22.error b/contrib/byacc/test/yacc/err_syntax22.error deleted file mode 100644 index 8622aa73f598..000000000000 --- a/contrib/byacc/test/yacc/err_syntax22.error +++ /dev/null @@ -1 +0,0 @@ -YACC: e - line 17 of "./err_syntax22.y", $2 (recur) is untyped diff --git a/contrib/unbound/doc/unbound.doxygen b/contrib/unbound/doc/unbound.doxygen deleted file mode 100644 index 7222dbc274e9..000000000000 --- a/contrib/unbound/doc/unbound.doxygen +++ /dev/null @@ -1,1656 +0,0 @@ -# Doxyfile 1.7.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = unbound - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 0.1 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = doc - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = YES - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = YES - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = YES - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -#SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = YES - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = NO - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -#SHOW_DIRECTORIES = YES - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated -# output files in an output format independent way. The create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = YES - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = NO - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = ./build \ - ./compat \ - ./contrib \ - util/configparser.c \ - util/configparser.h \ - util/configlexer.c \ - util/locks.h \ - pythonmod/doc \ - pythonmod/examples \ - pythonmod/unboundmodule.py \ - pythonmod/interface.h \ - pythonmod/ubmodule-msg.py \ - pythonmod/ubmodule-tst.py \ - unboundmodule.py \ - libunbound/python/unbound.py \ - libunbound/python/libunbound_wrap.c \ - libunbound/python/doc \ - libunbound/python/examples \ - ./ldns-src \ - README.md \ - doc/control_proto_spec.txt \ - doc/requirements.txt - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = YES - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -#COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# If the HTML_TIMESTAMP tag is set to YES then the generated HTML -# documentation will contain the timesstamp. - -HTML_TIMESTAMP = NO - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the stylesheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. - -#HTML_COLORSTYLE_HUE = 220 - -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. - -#HTML_COLORSTYLE_SAT = 100 - -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. - -#HTML_COLORSTYLE_GAMMA = 80 - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -#HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html -# for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. - -#DOCSET_PUBLISHER_ID = org.doxygen.Publisher - -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. - -#DOCSET_PUBLISHER_NAME = Publisher - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -#USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. - -#EXT_LINKS_IN_WINDOW = NO - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. - -#FORMULA_TRANSPARENT = YES - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = NO - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvances is that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -#PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = YES - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -#XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -#XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. -# This is useful -# if you want to understand what is going on. -# On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = *.h - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = DOXYGEN - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = ATTR_UNUSED - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -#PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -#MSCGEN_PATH = - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is -# allowed to run in parallel. When set to 0 (the default) doxygen will -# base this on the number of processors available in the system. You can set it -# explicitly to a value larger than 0 to get control over the balance -# between CPU load and processing speed. - -#DOT_NUM_THREADS = 0 - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -#DOT_FONTNAME = FreeSans.ttf - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/contrib/wpa/CONTRIBUTIONS b/contrib/wpa/CONTRIBUTIONS index 1b4caf7ac811..b2064dc83443 100644 --- a/contrib/wpa/CONTRIBUTIONS +++ b/contrib/wpa/CONTRIBUTIONS @@ -1,174 +1,174 @@ Contributions to hostap.git --------------------------- This software is distributed under a permissive open source license to allow it to be used in any projects, whether open source or proprietary. Contributions to the project are welcome and it is important to maintain clear record of contributions and terms under which they are licensed. To help with this, following procedure is used to allow acceptance and recording of the terms. All contributions are expected to be licensed under the modified BSD license (see below). Acknowledgment of the terms is tracked through inclusion of Signed-off-by tag in the contributions at the end of the commit log message. This tag indicates that the contributor agrees with the Developer Certificate of Origin (DCO) version 1.1 terms (see below; also available from http://developercertificate.org/). The current requirements for contributions to hostap.git -------------------------------------------------------- To indicate your acceptance of Developer's Certificate of Origin 1.1 terms, please add the following line to the end of the commit message for each contribution you make to the project: Signed-off-by: Your Name using your real name. Pseudonyms or anonymous contributions cannot unfortunately be accepted. The preferred method of submitting the contribution to the project is by email to the hostap mailing list: hostap@lists.infradead.org Note that the list may require subscription before accepting message without moderation. You can subscribe to the list at this address: http://lists.infradead.org/mailman/listinfo/hostap The message should contain an inlined patch against the current development branch (i.e., the master branch of git://w1.fi/hostap.git). Please make sure the software you use for sending the patch does not corrupt whitespace. If that cannot be fixed for some reason, it is better to include an attached version of the patch file than just send a whitespace damaged version in the message body. The patches should be separate logical changes rather than doing everything in a single patch. In other words, please keep cleanup, new features, and bug fixes all in their own patches. Each patch needs a commit log that describes the changes (what the changes fix, what functionality is added, why the changes are useful, etc.). Please try to follow the coding style used in the project. In general, the best way of generating a suitable formatted patch file is by committing the changes to a cloned git repository and using git format-patch. The patch can then be sent, e.g., with git send-email. A list of pending patches waiting for review is available in Patchwork: https://patchwork.ozlabs.org/project/hostap/list/ History of license and contributions terms ------------------------------------------ Until February 11, 2012, in case of most files in hostap.git, "under the open source license indicated in the file" means that the contribution is licensed both under GPL v2 and modified BSD license (see below) and the choice between these licenses is given to anyone who redistributes or uses the software. As such, the contribution has to be licensed under both options to allow this choice. As of February 11, 2012, the project has chosen to use only the BSD license option for future distribution. As such, the GPL v2 license option is no longer used and the contributions are not required to be licensed until GPL v2. In case of most files in hostap.git, "under the open source license indicated in the file" means that the contribution is licensed under the modified BSD license (see below). Until February 13, 2014, the project used an extended version of the DCO that included the identical items (a) through (d) from DCO 1.1 and an additional item (e): (e) The contribution can be licensed under the modified BSD license as shown below even in case of files that are currently licensed under other terms. This was used during the period when some of the files included the old license terms. Acceptance of this extended DCO version was indicated with a Signed-hostap tag in the commit message. This additional item (e) was used to collect explicit approval to license the contribution with only the modified BSD license (see below), i.e., without the GPL v2 option. This was done to allow simpler licensing terms to be used in the future. It should be noted that the modified BSD license is compatible with GNU GPL and as such, this possible move to simpler licensing option does not prevent use of this software in GPL projects. ===[ start quote from http://developercertificate.org/ ]======================= Developer Certificate of Origin Version 1.1 Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 660 York Street, Suite 102, San Francisco, CA 94110 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. ===[ end quote from http://developercertificate.org/ ]========================= The license terms used for hostap.git files ------------------------------------------- Modified BSD license (no advertisement clause): -Copyright (c) 2002-2021, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name(s) of the above-listed copyright holder(s) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/wpa/COPYING b/contrib/wpa/COPYING index 5d0115c9ca6f..7ca30301e28b 100644 --- a/contrib/wpa/COPYING +++ b/contrib/wpa/COPYING @@ -1,22 +1,22 @@ wpa_supplicant and hostapd -------------------------- -Copyright (c) 2002-2019, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. See the README file for the current license terms. This software was previously distributed under BSD/GPL v2 dual license terms that allowed either of those license alternatives to be selected. As of February 11, 2012, the project has chosen to use only the BSD license option for future distribution. As such, the GPL v2 license option is no longer used. It should be noted that the BSD license option (the one with advertisement clause removed) is compatible with GPL and as such, does not prevent use of this software in projects that use GPL. Some of the files may still include pointers to GPL version 2 license terms. However, such copyright and license notifications are maintained only for attribution purposes and any distribution of this software after February 11, 2012 is no longer under the GPL v2 option. diff --git a/contrib/wpa/README b/contrib/wpa/README index a9f806967bf9..1470c4f23582 100644 --- a/contrib/wpa/README +++ b/contrib/wpa/README @@ -1,56 +1,56 @@ wpa_supplicant and hostapd -------------------------- -Copyright (c) 2002-2019, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. These programs are licensed under the BSD license (the one with advertisement clause removed). If you are submitting changes to the project, please see CONTRIBUTIONS file for more instructions. This package may include either wpa_supplicant, hostapd, or both. See README file respective subdirectories (wpa_supplicant/README or hostapd/README) for more details. Source code files were moved around in v0.6.x releases and compared to earlier releases, the programs are now built by first going to a subdirectory (wpa_supplicant or hostapd) and creating build configuration (.config) and running 'make' there (for Linux/BSD/cygwin builds). License ------- This software may be distributed, used, and modified under the terms of BSD license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name(s) of the above-listed copyright holder(s) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog index 34a8a081879d..279298e4d4d4 100644 --- a/contrib/wpa/hostapd/ChangeLog +++ b/contrib/wpa/hostapd/ChangeLog @@ -1,1278 +1,1321 @@ ChangeLog for hostapd +2022-01-16 - v2.10 + * SAE changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + - added option send SAE Confirm immediately (sae_config_immediate=1) + after SAE Commit + - added support for the hash-to-element mechanism (sae_pwe=1 or + sae_pwe=2) + - fixed PMKSA caching with OKC + - added support for SAE-PK + * EAP-pwd changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + * fixed WPS UPnP SUBSCRIBE handling of invalid operations + [https://w1.fi/security/2020-1/] + * fixed PMF disconnection protection bypass + [https://w1.fi/security/2019-7/] + * added support for using OpenSSL 3.0 + * fixed various issues in experimental support for EAP-TEAP server + * added configuration (max_auth_rounds, max_auth_rounds_short) to + increase the maximum number of EAP message exchanges (mainly to + support cases with very large certificates) for the EAP server + * added support for DPP release 2 (Wi-Fi Device Provisioning Protocol) + * extended HE (IEEE 802.11ax) support, including 6 GHz support + * removed obsolete IAPP functionality + * fixed EAP-FAST server with TLS GCM/CCM ciphers + * dropped support for libnl 1.1 + * added support for nl80211 control port for EAPOL frame TX/RX + * fixed OWE key derivation with groups 20 and 21; this breaks backwards + compatibility for these groups while the default group 19 remains + backwards compatible; owe_ptk_workaround=1 can be used to enabled a + a workaround for the group 20/21 backwards compatibility + * added support for Beacon protection + * added support for Extended Key ID for pairwise keys + * removed WEP support from the default build (CONFIG_WEP=y can be used + to enable it, if really needed) + * added a build option to remove TKIP support (CONFIG_NO_TKIP=y) + * added support for Transition Disable mechanism to allow the AP to + automatically disable transition mode to improve security + * added support for PASN + * added EAP-TLS server support for TLS 1.3 (disabled by default for now) + * a large number of other fixes, cleanup, and extensions + 2019-08-07 - v2.9 * SAE changes - disable use of groups using Brainpool curves - improved protection against side channel attacks [https://w1.fi/security/2019-6/] * EAP-pwd changes - disable use of groups using Brainpool curves - improved protection against side channel attacks [https://w1.fi/security/2019-6/] * fixed FT-EAP initial mobility domain association using PMKSA caching * added configuration of airtime policy * fixed FILS to and RSNE into (Re)Association Response frames * fixed DPP bootstrapping URI parser of channel list * added support for regulatory WMM limitation (for ETSI) * added support for MACsec Key Agreement using IEEE 802.1X/PSK * added experimental support for EAP-TEAP server (RFC 7170) * added experimental support for EAP-TLS server with TLS v1.3 * added support for two server certificates/keys (RSA/ECC) * added AKMSuiteSelector into "STA " control interface data to determine with AKM was used for an association * added eap_sim_id parameter to allow EAP-SIM/AKA server pseudonym and fast reauthentication use to be disabled * fixed an ECDH operation corner case with OpenSSL 2019-04-21 - v2.8 * SAE changes - added support for SAE Password Identifier - changed default configuration to enable only group 19 (i.e., disable groups 20, 21, 25, 26 from default configuration) and disable all unsuitable groups completely based on REVmd changes - improved anti-clogging token mechanism and SAE authentication frame processing during heavy CPU load; this mitigates some issues with potential DoS attacks trying to flood an AP with large number of SAE messages - added Finite Cyclic Group field in status code 77 responses - reject use of unsuitable groups based on new implementation guidance in REVmd (allow only FFC groups with prime >= 3072 bits and ECC groups with prime >= 256) - minimize timing and memory use differences in PWE derivation [https://w1.fi/security/2019-1/] (CVE-2019-9494) - fixed confirm message validation in error cases [https://w1.fi/security/2019-3/] (CVE-2019-9496) * EAP-pwd changes - minimize timing and memory use differences in PWE derivation [https://w1.fi/security/2019-2/] (CVE-2019-9495) - verify peer scalar/element [https://w1.fi/security/2019-4/] (CVE-2019-9497 and CVE-2019-9498) - fix message reassembly issue with unexpected fragment [https://w1.fi/security/2019-5/] - enforce rand,mask generation rules more strictly - fix a memory leak in PWE derivation - disallow ECC groups with a prime under 256 bits (groups 25, 26, and 27) * Hotspot 2.0 changes - added support for release number 3 - reject release 2 or newer association without PMF * added support for RSN operating channel validation (CONFIG_OCV=y and configuration parameter ocv=1) * added Multi-AP protocol support * added FTM responder configuration * fixed build with LibreSSL * added FT/RRB workaround for short Ethernet frame padding * fixed KEK2 derivation for FILS+FT * added RSSI-based association rejection from OCE * extended beacon reporting functionality * VLAN changes - allow local VLAN management with remote RADIUS authentication - add WPA/WPA2 passphrase/PSK -based VLAN assignment * OpenSSL: allow systemwide policies to be overridden * extended PEAP to derive EMSK to enable use with ERP/FILS * extended WPS to allow SAE configuration to be added automatically for PSK (wps_cred_add_sae=1) * fixed FT and SA Query Action frame with AP-MLME-in-driver cases * OWE: allow Diffie-Hellman Parameter element to be included with DPP in preparation for DPP protocol extension * RADIUS server: started to accept ERP keyName-NAI as user identity automatically without matching EAP database entry * fixed PTK rekeying with FILS and FT 2018-12-02 - v2.7 * fixed WPA packet number reuse with replayed messages and key reinstallation [http://w1.fi/security/2017-1/] (CVE-2017-13082) * added support for FILS (IEEE 802.11ai) shared key authentication * added support for OWE (Opportunistic Wireless Encryption, RFC 8110; and transition mode defined by WFA) * added support for DPP (Wi-Fi Device Provisioning Protocol) * FT: - added local generation of PMK-R0/PMK-R1 for FT-PSK (ft_psk_generate_local=1) - replaced inter-AP protocol with a cleaner design that is more easily extensible; this breaks backward compatibility and requires all APs in the ESS to be updated at the same time to maintain FT functionality - added support for wildcard R0KH/R1KH - replaced r0_key_lifetime (minutes) parameter with ft_r0_key_lifetime (seconds) - fixed wpa_psk_file use for FT-PSK - fixed FT-SAE PMKID matching - added expiration to PMK-R0 and PMK-R1 cache - added IEEE VLAN support (including tagged VLANs) - added support for SHA384 based AKM * SAE - fixed some PMKSA caching cases with SAE - added support for configuring SAE password separately of the WPA2 PSK/passphrase - added option to require MFP for SAE associations (sae_require_pmf=1) - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection for SAE; note: this is not backwards compatible, i.e., both the AP and station side implementations will need to be update at the same time to maintain interoperability - added support for Password Identifier * hostapd_cli: added support for command history and completion * added support for requesting beacon report * large number of other fixes, cleanup, and extensions * added option to configure EAPOL-Key retry limits (wpa_group_update_count and wpa_pairwise_update_count) * removed all PeerKey functionality * fixed nl80211 AP mode configuration regression with Linux 4.15 and newer * added support for using wolfSSL cryptographic library * fixed some 20/40 MHz coexistence cases where the BSS could drop to 20 MHz even when 40 MHz would be allowed * Hotspot 2.0 - added support for setting Venue URL ANQP-element (venue_url) - added support for advertising Hotspot 2.0 operator icons - added support for Roaming Consortium Selection element - added support for Terms and Conditions - added support for OSEN connection in a shared RSN BSS * added support for using OpenSSL 1.1.1 * added EAP-pwd server support for salted passwords 2016-10-02 - v2.6 * fixed EAP-pwd last fragment validation [http://w1.fi/security/2015-7/] (CVE-2015-5314) * fixed WPS configuration update vulnerability with malformed passphrase [http://w1.fi/security/2016-1/] (CVE-2016-4476) * extended channel switch support for VHT bandwidth changes * added support for configuring new ANQP-elements with anqp_elem=: * fixed Suite B 192-bit AKM to use proper PMK length (note: this makes old releases incompatible with the fixed behavior) * added no_probe_resp_if_max_sta=1 parameter to disable Probe Response frame sending for not-associated STAs if max_num_sta limit has been reached * added option (-S as command line argument) to request all interfaces to be started at the same time * modified rts_threshold and fragm_threshold configuration parameters to allow -1 to be used to disable RTS/fragmentation * EAP-pwd: added support for Brainpool Elliptic Curves (with OpenSSL 1.0.2 and newer) * fixed EAPOL reauthentication after FT protocol run * fixed FTIE generation for 4-way handshake after FT protocol run * fixed and improved various FST operations * TLS server - support SHA384 and SHA512 hashes - support TLS v1.2 signature algorithm with SHA384 and SHA512 - support PKCS #5 v2.0 PBES2 - support PKCS #5 with PKCS #12 style key decryption - minimal support for PKCS #12 - support OCSP stapling (including ocsp_multi) * added support for OpenSSL 1.1 API changes - drop support for OpenSSL 0.9.8 - drop support for OpenSSL 1.0.0 * EAP-PEAP: support fast-connect crypto binding * RADIUS - fix Called-Station-Id to not escape SSID - add Event-Timestamp to all Accounting-Request packets - add Acct-Session-Id to Accounting-On/Off - add Acct-Multi-Session-Id ton Access-Request packets - add Service-Type (= Frames) - allow server to provide PSK instead of passphrase for WPA-PSK Tunnel_password case - update full message for interim accounting updates - add Acct-Delay-Time into Accounting messages - add require_message_authenticator configuration option to require CoA/Disconnect-Request packets to be authenticated * started to postpone WNM-Notification frame sending by 100 ms so that the STA has some more time to configure the key before this frame is received after the 4-way handshake * VHT: added interoperability workaround for 80+80 and 160 MHz channels * extended VLAN support (per-STA vif, etc.) * fixed PMKID derivation with SAE * nl80211 - added support for full station state operations - fix IEEE 802.1X/WEP EAP reauthentication and rekeying to use unencrypted EAPOL frames * added initial MBO support; number of extensions to WNM BSS Transition Management * added initial functionality for location related operations * added assocresp_elements parameter to allow vendor specific elements to be added into (Re)Association Response frames * improved Public Action frame addressing - use Address 3 = wildcard BSSID in GAS response if a query from an unassociated STA used that address - fix TX status processing for Address 3 = wildcard BSSID - add gas_address3 configuration parameter to control Address 3 behavior * added command line parameter -i to override interface parameter in hostapd.conf * added command completion support to hostapd_cli * added passive client taxonomy determination (CONFIG_TAXONOMY=y compile option and "SIGNATURE " control interface command) * number of small fixes 2015-09-27 - v2.5 * fixed WPS UPnP vulnerability with HTTP chunked transfer encoding [http://w1.fi/security/2015-2/] (CVE-2015-4141) * fixed WMM Action frame parser [http://w1.fi/security/2015-3/] (CVE-2015-4142) * fixed EAP-pwd server missing payload length validation [http://w1.fi/security/2015-4/] (CVE-2015-4143, CVE-2015-4144, CVE-2015-4145) * fixed validation of WPS and P2P NFC NDEF record payload length [http://w1.fi/security/2015-5/] * nl80211: - fixed vendor command handling to check OUI properly * fixed hlr_auc_gw build with OpenSSL * hlr_auc_gw: allow Milenage RES length to be reduced * disable HT for a station that does not support WMM/QoS * added support for hashed password (NtHash) in EAP-pwd server * fixed and extended dynamic VLAN cases * added EAP-EKE server support for deriving Session-Id * set Acct-Session-Id to a random value to make it more likely to be unique even if the device does not have a proper clock * added more 2.4 GHz channels for 20/40 MHz HT co-ex scan * modified SAE routines to be more robust and PWE generation to be stronger against timing attacks * added support for Brainpool Elliptic Curves with SAE * increases maximum value accepted for cwmin/cwmax * added support for CCMP-256 and GCMP-256 as group ciphers with FT * added Fast Session Transfer (FST) module * removed optional fields from RSNE when using FT with PMF (workaround for interoperability issues with iOS 8.4) * added EAP server support for TLS session resumption * fixed key derivation for Suite B 192-bit AKM (this breaks compatibility with the earlier version) * added mechanism to track unconnected stations and do minimal band steering * number of small fixes 2015-03-15 - v2.4 * allow OpenSSL cipher configuration to be set for internal EAP server (openssl_ciphers parameter) * fixed number of small issues based on hwsim test case failures and static analyzer reports * fixed Accounting-Request to not include duplicated Acct-Session-Id * add support for Acct-Multi-Session-Id in RADIUS Accounting messages * add support for PMKSA caching with SAE * add support for generating BSS Load element (bss_load_update_period) * fixed channel switch from VHT to HT * add INTERFACE-ENABLED and INTERFACE-DISABLED ctrl_iface events * add support for learning STA IPv4/IPv6 addresses and configuring ProxyARP support * dropped support for the madwifi driver interface * add support for Suite B (128-bit and 192-bit level) key management and cipher suites * fixed a regression with driver=wired * extend EAPOL-Key msg 1/4 retry workaround for changing SNonce * add BSS_TM_REQ ctrl_iface command to send BSS Transition Management Request frames and BSS-TM-RESP event to indicate response to such frame * add support for EAP Re-Authentication Protocol (ERP) * fixed AP IE in EAPOL-Key 3/4 when both WPA and FT was enabled * fixed a regression in HT 20/40 coex Action frame parsing * set stdout to be line-buffered * add support for vendor specific VHT extension to enable 256 QAM rates (VHT-MCS 8 and 9) on 2.4 GHz band * RADIUS DAS: - extend Disconnect-Request processing to allow matching of multiple sessions - support Acct-Multi-Session-Id as an identifier - allow PMKSA cache entry to be removed without association * expire hostapd STA entry if kernel does not have a matching entry * allow chanlist to be used to specify a subset of channels for ACS * improve ACS behavior on 2.4 GHz band and allow channel bias to be configured with acs_chan_bias parameter * do not reply to a Probe Request frame that includes DSS Parameter Set element in which the channel does not match the current operating channel * add UPDATE_BEACON ctrl_iface command; this can be used to force Beacon frame contents to be updated and to start beaconing on an interface that used start_disabled=1 * fixed some RADIUS server failover cases 2014-10-09 - v2.3 * fixed number of minor issues identified in static analyzer warnings * fixed DFS and channel switch operation for multi-BSS cases * started to use constant time comparison for various password and hash values to reduce possibility of any externally measurable timing differences * extended explicit clearing of freed memory and expired keys to avoid keeping private data in memory longer than necessary * added support for number of new RADIUS attributes from RFC 7268 (Mobility-Domain-Id, WLAN-HESSID, WLAN-Pairwise-Cipher, WLAN-Group-Cipher, WLAN-AKM-Suite, WLAN-Group-Mgmt-Pairwise-Cipher) * fixed GET_CONFIG wpa_pairwise_cipher value * added code to clear bridge FDB entry on station disconnection * fixed PMKSA cache timeout from Session-Timeout for WPA/WPA2 cases * fixed OKC PMKSA cache entry fetch to avoid a possible infinite loop in case the first entry does not match * fixed hostapd_cli action script execution to use more robust mechanism (CVE-2014-3686) 2014-06-04 - v2.2 * fixed SAE confirm-before-commit validation to avoid a potential segmentation fault in an unexpected message sequence that could be triggered remotely * extended VHT support - Operating Mode Notification - Power Constraint element (local_pwr_constraint) - Spectrum management capability (spectrum_mgmt_required=1) - fix VHT80 segment picking in ACS - fix vht_capab 'Maximum A-MPDU Length Exponent' handling - fix VHT20 * fixed HT40 co-ex scan for some pri/sec channel switches * extended HT40 co-ex support to allow dynamic channel width changes during the lifetime of the BSS * fixed HT40 co-ex support to check for overlapping 20 MHz BSS * fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding; this fixes password with include UTF-8 characters that use three-byte encoding EAP methods that use NtPasswordHash * reverted TLS certificate validation step change in v2.1 that rejected any AAA server certificate with id-kp-clientAuth even if id-kp-serverAuth EKU was included * fixed STA validation step for WPS ER commands to prevent a potential crash if an ER sends an unexpected PutWLANResponse to a station that is disassociated, but not fully removed * enforce full EAP authentication after RADIUS Disconnect-Request by removing the PMKSA cache entry * added support for NAS-IP-Address, NAS-identifier, and NAS-IPv6-Address in RADIUS Disconnect-Request * added mechanism for removing addresses for MAC ACLs by prefixing an entry with "-" * Interworking/Hotspot 2.0 enhancements - support Hotspot 2.0 Release 2 * OSEN network for online signup connection * subscription remediation (based on RADIUS server request or control interface HS20_WNM_NOTIF for testing purposes) * Hotspot 2.0 release number indication in WFA RADIUS VSA * deauthentication request (based on RADIUS server request or control interface WNM_DEAUTH_REQ for testing purposes) * Session Info URL RADIUS AVP to trigger ESS Disassociation Imminent * hs20_icon config parameter to configure icon files for OSU * osu_* config parameters for OSU Providers list - do not use Interworking filtering rules on Probe Request if Interworking is disabled to avoid interop issues * added/fixed nl80211 functionality - AP interface teardown optimization - support vendor specific driver command (VENDOR []) * fixed PMF protection of Deauthentication frame when this is triggered by session timeout * internal TLS implementation enhancements/fixes - add SHA256-based cipher suites - add DHE-RSA cipher suites - fix X.509 validation of PKCS#1 signature to check for extra data * RADIUS server functionality - add minimal RADIUS accounting server support (hostapd-as-server); this is mainly to enable testing coverage with hwsim scripts - allow authentication log to be written into SQLite database - added option for TLS protocol testing of an EAP peer by simulating various misbehaviors/known attacks - MAC ACL support for testing purposes * fixed PTK derivation for CCMP-256 and GCMP-256 * extended WPS per-station PSK to support ER case * added option to configure the management group cipher (group_mgmt_cipher=AES-128-CMAC (default), BIP-GMAC-128, BIP-GMAC-256, BIP-CMAC-256) * fixed AP mode default TXOP Limit values for AC_VI and AC_VO (these were rounded incorrectly) * added support for postponing FT response in case PMK-R1 needs to be pulled from R0KH * added option to advertise 40 MHz intolerant HT capability with ht_capab=[40-INTOLERANT] * remove WPS 1.0 only support, i.e., WSC 2.0 support is now enabled whenever CONFIG_WPS=y is set * EAP-pwd fixes - fix possible segmentation fault on EAP method deinit if an invalid group is negotiated * fixed RADIUS client retransmit/failover behavior - there was a potential ctash due to freed memory being accessed - failover to a backup server mechanism did not work properly * fixed a possible crash on double DISABLE command when multiple BSSes are enabled * fixed a memory leak in SAE random number generation * fixed GTK rekeying when the station uses FT protocol * fixed off-by-one bounds checking in printf_encode() - this could result in deinial of service in some EAP server cases * various bug fixes 2014-02-04 - v2.1 * added support for simultaneous authentication of equals (SAE) for stronger password-based authentication with WPA2-Personal * added nl80211 functionality - VHT configuration for nl80211 - support split wiphy dump - driver-based MAC ACL - QoS Mapping configuration * added fully automated regression testing with mac80211_hwsim * allow ctrl_iface group to be specified on command line (-G) * allow single hostapd process to control independent WPS interfaces (wps_independent=1) instead of synchronized operations through all configured interfaces within a process * avoid processing received management frames multiple times when using nl80211 with multiple BSSes * added support for DFS (processing radar detection events, CAC, channel re-selection) * added EAP-EKE server * added automatic channel selection (ACS) * added option for using per-BSS (vif) configuration files with -b: * extended global control interface ADD/REMOVE commands to allow BSSes of a radio to be removed individually without having to add/remove all other BSSes of the radio at the same time * added support for sending debug info to Linux tracing (-T on command line) * replace dump_file functionality with same information being available through the hostapd control interface * added support for using Protected Dual of Public Action frames for GAS/ANQP exchanges when PMF is enabled * added support for WPS+NFC updates - improved protocol - option to fetch and report alternative carrier records for external NFC operations * various bug fixes 2013-01-12 - v2.0 * added AP-STA-DISCONNECTED ctrl_iface event * improved debug logging (human readable event names, interface name included in more entries) * added number of small changes to make it easier for static analyzers to understand the implementation * added a workaround for Windows 7 Michael MIC failure reporting and use of the Secure bit in EAPOL-Key msg 3/4 * fixed number of small bugs (see git logs for more details) * changed OpenSSL to read full certificate chain from server_cert file * nl80211: number of updates to use new cfg80211/nl80211 functionality - replace monitor interface with nl80211 commands - additional information for driver-based AP SME * EAP-pwd: - fix KDF for group 21 and zero-padding - added support for fragmentation - increased maximum number of hunting-and-pecking iterations * avoid excessive Probe Response retries for broadcast Probe Request frames (only with drivers using hostapd SME/MLME) * added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y) * fixed WPS operation stopping on dual concurrent AP * added wps_rf_bands configuration parameter for overriding RF Bands value for WPS * added support for getting per-device PSK from RADIUS Tunnel-Password * added support for libnl 3.2 and newer * increased initial group key handshake retransmit timeout to 500 ms * added a workaround for 4-way handshake to update SNonce even after having sent EAPOL-Key 3/4 to avoid issues with some supplicant implementations that can change SNonce for each EAP-Key 2/4 * added a workaround for EAPOL-Key 4/4 using incorrect type value in WPA2 mode (some deployed stations use WPA type in that message) * added a WPS workaround for mixed mode AP Settings with Windows 7 * changed WPS AP PIN disabling mechanism to disable the PIN after 10 consecutive failures in addition to using the exponential lockout period * added support for WFA Hotspot 2.0 - GAS/ANQP advertisement of network information - disable_dgaf parameter to disable downstream group-addressed forwarding * simplified licensing terms by selecting the BSD license as the only alternative * EAP-SIM: fixed re-authentication not to update pseudonym * EAP-SIM: use Notification round before EAP-Failure * EAP-AKA: added support for AT_COUNTER_TOO_SMALL * EAP-AKA: skip AKA/Identity exchange if EAP identity is recognized * EAP-AKA': fixed identity for MK derivation * EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this breaks interoperability with older versions * EAP-SIM/AKA: allow pseudonym to be used after unknown reauth id * changed ANonce to be a random number instead of Counter-based * added support for canceling WPS operations with hostapd_cli wps_cancel * fixed EAP/WPS to PSK transition on reassociation in cases where deauthentication is missed * hlr_auc_gw enhancements: - a new command line parameter -u can be used to enable updating of SQN in Milenage file - use 5 bit IND for SQN updates - SQLite database can now be used to store Milenage information * EAP-SIM/AKA DB: added optional use of SQLite database for pseudonyms and reauth data * added support for Chargeable-User-Identity (RFC 4372) * added radius_auth_req_attr and radius_acct_req_attr configuration parameters to allow adding/overriding of RADIUS attributes in Access-Request and Accounting-Request packets * added support for RADIUS dynamic authorization server (RFC 5176) * added initial support for WNM operations - BSS max idle period - WNM-Sleep Mode * added new WPS NFC ctrl_iface mechanism - removed obsoleted WPS_OOB command (including support for deprecated UFD config_method) * added FT support for drivers that implement MLME internally * added SA Query support for drivers that implement MLME internally * removed default ACM=1 from AC_VO and AC_VI * changed VENDOR-TEST EAP method to use proper private enterprise number (this will not interoperate with older versions) * added hostapd.conf parameter vendor_elements to allow arbitrary vendor specific elements to be added to the Beacon and Probe Response frames * added support for configuring GCMP cipher for IEEE 802.11ad * added support for 256-bit AES with internal TLS implementation * changed EAPOL transmission to use AC_VO if WMM is active * fixed EAP-TLS/PEAP/TTLS/FAST server to validate TLS Message Length correctly; invalid messages could have caused the hostapd process to terminate before this fix [CVE-2012-4445] * limit number of active wildcard PINs for WPS Registrar to one to avoid confusing behavior with multiple wildcard PINs * added a workaround for WPS PBC session overlap detection to avoid interop issues with deployed station implementations that do not remove active PBC indication from Probe Request frames properly * added support for using SQLite for the eap_user database * added Acct-Session-Id attribute into Access-Request messages * fixed EAPOL frame transmission to non-QoS STAs with nl80211 (do not send QoS frames if the STA did not negotiate use of QoS for this association) 2012-05-10 - v1.0 * Add channel selection support in hostapd. See hostapd.conf. * Add support for IEEE 802.11v Time Advertisement mechanism with UTC TSF offset. See hostapd.conf for config info. * Delay STA entry removal until Deauth/Disassoc TX status in AP mode. This allows the driver to use PS buffering of Deauthentication and Disassociation frames when the STA is in power save sleep. Only available with drivers that provide TX status events for Deauth/ Disassoc frames (nl80211). * Allow PMKSA caching to be disabled on the Authenticator. See hostap.conf config parameter disable_pmksa_caching. * atheros: Add support for IEEE 802.11w configuration. * bsd: Add support for setting HT values in IFM_MMASK. * Allow client isolation to be configured with ap_isolate. Client isolation can be used to prevent low-level bridging of frames between associated stations in the BSS. By default, this bridging is allowed. * Allow coexistance of HT BSSes with WEP/TKIP BSSes. * Add require_ht config parameter, which can be used to configure hostapd to reject association with any station that does not support HT PHY. * Add support for writing debug log to a file using "-f" option. Also add relog CLI command to re-open the log file. * Add bridge handling for WDS STA interfaces. By default they are added to the configured bridge of the AP interface (if present), but the user can also specify a separate bridge using cli command wds_bridge. * hostapd_cli: - Add wds_bridge command for specifying bridge for WDS STA interfaces. - Add relog command for reopening log file. - Send AP-STA-DISCONNECTED event when an AP disconnects a station due to inactivity. - Add wps_config ctrl_interface command for configuring AP. This command can be used to configure the AP using the internal WPS registrar. It works in the same way as new AP settings received from an ER. - Many WPS/WPS ER commands - see WPS/WPS ER sections for details. - Add command get version, that returns hostapd version string. * WNM: Add BSS Transition Management Request for ESS Disassoc Imminent. Use hostapd_cli ess_disassoc (STA addr) (URL) to send the notification to the STA. * Allow AP mode to disconnect STAs based on low ACK condition (when the data connection is not working properly, e.g., due to the STA going outside the range of the AP). Disabled by default, enable by config option disassoc_low_ack. * Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad config file. * WPS: - Send AP Settings as a wrapped Credential attribute to ctrl_iface in WPS-NEW-AP-SETTINGS. - Dispatch more WPS events through hostapd ctrl_iface. - Add mechanism for indicating non-standard WPS errors. - Change concurrent radio AP to use only one WPS UPnP instance. - Add wps_check_pin command for processing PIN from user input. UIs can use this command to process a PIN entered by a user and to validate the checksum digit (if present). - Add hostap_cli get_config command to display current AP config. - Add new hostapd_cli command, wps_ap_pin, to manage AP PIN at runtime and support dynamic AP PIN management. - Disable AP PIN after 10 consecutive failures. Slow down attacks on failures up to 10. - Allow AP to start in Enrollee mode without AP PIN for probing, to be compatible with Windows 7. - Add Config Error into WPS-FAIL events to provide more info to the user on how to resolve the issue. - When controlling multiple interfaces: - apply WPS commands to all interfaces configured to use WPS - apply WPS config changes to all interfaces that use WPS - when an attack is detected on any interface, disable AP PIN on all interfaces * WPS ER: - Show SetSelectedRegistrar events as ctrl_iface events. - Add special AP Setup Locked mode to allow read only ER. ap_setup_locked=2 can now be used to enable a special mode where WPS ER can learn the current AP settings, but cannot change them. * WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2) - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool for testing protocol extensibility. - Add build option CONFIG_WPS_STRICT to allow disabling of WPS workarounds. - Add support for AuthorizedMACs attribute. * TDLS: - Allow TDLS use or TDLS channel switching in the BSS to be prohibited in the BSS, using config params tdls_prohibit and tdls_prohibit_chan_switch. * EAP server: Add support for configuring fragment size (see fragment_size in hostapd.conf). * wlantest: Add a tool wlantest for IEEE802.11 protocol testing. wlantest can be used to capture frames from a monitor interface for realtime capturing or from pcap files for offline analysis. * Interworking: Support added for 802.11u. Enable in .config with CONFIG_INTERWORKING. See hostapd.conf for config parameters for interworking. * Android: Add build and runtime support for Android hostapd. * Add a new debug message level for excessive information. Use -ddd to enable. * TLS: Add support for tls_disable_time_checks=1 in client mode. * Internal TLS: - Add support for TLS v1.1 (RFC 4346). Enable with build parameter CONFIG_TLSV11. - Add domainComponent parser for X.509 names * Reorder some IEs to get closer to IEEE 802.11 standard. Move WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames. Move HT IEs to be later in (Re)Assoc Resp. * Many bugfixes. 2010-04-18 - v0.7.2 * fix WPS internal Registrar use when an external Registrar is also active * bsd: Cleaned up driver wrapper and added various low-level configuration options * TNC: fixed issues with fragmentation * EAP-TNC: add Flags field into fragment acknowledgement (needed to interoperate with other implementations; may potentially breaks compatibility with older wpa_supplicant/hostapd versions) * cleaned up driver wrapper API for multi-BSS operations * nl80211: fix multi-BSS and VLAN operations * fix number of issues with IEEE 802.11r/FT; this version is not backwards compatible with old versions * add SA Query Request processing in AP mode (IEEE 802.11w) * fix IGTK PN in group rekeying (IEEE 802.11w) * fix WPS PBC session overlap detection to use correct attribute * hostapd_notif_Assoc() can now be called with all IEs to simplify driver wrappers * work around interoperability issue with some WPS External Registrar implementations * nl80211: fix WPS IE update * hostapd_cli: add support for action script operations (run a script on hostapd events) * fix DH padding with internal crypto code (mainly, for WPS) * fix WPS association with both WPS IE and WPA/RSN IE present with driver wrappers that use hostapd MLME (e.g., nl80211) 2010-01-16 - v0.7.1 * cleaned up driver wrapper API (struct wpa_driver_ops); the new API is not fully backwards compatible, so out-of-tree driver wrappers will need modifications * cleaned up various module interfaces * merge hostapd and wpa_supplicant developers' documentation into a single document * fixed HT Capabilities IE with nl80211 drivers * moved generic AP functionality code into src/ap * WPS: handle Selected Registrar as union of info from all Registrars * remove obsolete Prism54.org driver wrapper * added internal debugging mechanism with backtrace support and memory allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) * EAP-FAST server: piggyback Phase 2 start with the end of Phase 1 * WPS: add support for dynamically selecting whether to provision the PSK as an ASCII passphrase or PSK * added support for WDS (4-address frame) mode with per-station virtual interfaces (wds_sta=1 in config file; only supported with driver=nl80211 for now) * fixed WPS Probe Request processing to handle missing required attribute * fixed PKCS#12 use with OpenSSL 1.0.0 * detect bridge interface automatically so that bridge parameter in hostapd.conf becomes optional (though, it may now be used to automatically add then WLAN interface into a bridge with driver=nl80211) 2009-11-21 - v0.7.0 * increased hostapd_cli ping interval to 5 seconds and made this configurable with a new command line options (-G) * driver_nl80211: use Linux socket filter to improve performance * added support for external Registrars with WPS (UPnP transport) * 802.11n: scan for overlapping BSSes before starting 20/40 MHz channel * driver_nl80211: fixed STA accounting data collection (TX/RX bytes reported correctly; TX/RX packets not yet available from kernel) * added support for WPS USBA out-of-band mechanism with USB Flash Drives (UFD) (CONFIG_WPS_UFD=y) * fixed EAPOL/EAP reauthentication when using an external RADIUS authentication server * fixed TNC with EAP-TTLS * fixed IEEE 802.11r key derivation function to match with the standard (note: this breaks interoperability with previous version) [Bug 303] * fixed SHA-256 based key derivation function to match with the standard when using CCMP (for IEEE 802.11r and IEEE 802.11w) (note: this breaks interoperability with previous version) [Bug 307] * added number of code size optimizations to remove unnecessary functionality from the program binary based on build configuration (part of this automatic; part configurable with CONFIG_NO_* build options) * use shared driver wrapper files with wpa_supplicant * driver_nl80211: multiple updates to provide support for new Linux nl80211/mac80211 functionality * updated management frame protection to use IEEE Std 802.11w-2009 * fixed number of small WPS issues and added workarounds to interoperate with common deployed broken implementations * added some IEEE 802.11n co-existence rules to disable 40 MHz channels or modify primary/secondary channels if needed based on neighboring networks * added support for NFC out-of-band mechanism with WPS * added preliminary support for IEEE 802.11r RIC processing 2009-01-06 - v0.6.7 * added support for Wi-Fi Protected Setup (WPS) (hostapd can now be configured to act as an integrated WPS Registrar and provision credentials for WPS Enrollees using PIN and PBC methods; external wireless Registrar can configure the AP, but external WLAN Manager Registrars are not supported); WPS support can be enabled by adding CONFIG_WPS=y into .config and setting the runtime configuration variables in hostapd.conf (see WPS section in the example configuration file); new hostapd_cli commands wps_pin and wps_pbc are used to configure WPS negotiation; see README-WPS for more details * added IEEE 802.11n HT capability configuration (ht_capab) * added support for generating Country IE based on nl80211 regulatory information (added if ieee80211d=1 in configuration) * fixed WEP authentication (both Open System and Shared Key) with mac80211 * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) * added support for using driver_test over UDP socket * changed EAP-GPSK to use the IANA assigned EAP method type 51 * updated management frame protection to use IEEE 802.11w/D7.0 * fixed retransmission of EAP requests if no response is received 2008-11-23 - v0.6.6 * added a new configuration option, wpa_ptk_rekey, that can be used to enforce frequent PTK rekeying, e.g., to mitigate some attacks against TKIP deficiencies * updated OpenSSL code for EAP-FAST to use an updated version of the session ticket overriding API that was included into the upstream OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is needed with that version anymore) * changed channel flags configuration to read the information from the driver (e.g., via driver_nl80211 when using mac80211) instead of using hostapd as the source of the regulatory information (i.e., information from CRDA is now used with mac80211); this allows 5 GHz channels to be used with hostapd (if allowed in the current regulatory domain) * fixed EAP-TLS message processing for the last TLS message if it is large enough to require fragmentation (e.g., if a large Session Ticket data is included) * fixed listen interval configuration for nl80211 drivers 2008-11-01 - v0.6.5 * added support for SHA-256 as X.509 certificate digest when using the internal X.509/TLSv1 implementation * fixed EAP-FAST PAC-Opaque padding (0.6.4 broke this for some peer identity lengths) * fixed internal TLSv1 implementation for abbreviated handshake (used by EAP-FAST server) * added support for setting VLAN ID for STAs based on local MAC ACL (accept_mac_file) as an alternative for RADIUS server-based configuration * updated management frame protection to use IEEE 802.11w/D6.0 (adds a new association ping to protect against unauthenticated authenticate or (re)associate request frames dropping association) * added support for using SHA256-based stronger key derivation for WPA2 (IEEE 802.11w) * added new "driver wrapper" for RADIUS-only configuration (driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config) * fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2) is enabled in configuration * changed EAP-FAST configuration to use separate fields for A-ID and A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed 16-octet len binary value for better interoperability with some peer implementations; eap_fast_a_id is now configured as a hex string * driver_nl80211: Updated to match the current Linux mac80211 AP mode configuration (wireless-testing.git and Linux kernel releases starting from 2.6.29) 2008-08-10 - v0.6.4 * added peer identity into EAP-FAST PAC-Opaque and skip Phase 2 Identity Request if identity is already known * added support for EAP Sequences in EAP-FAST Phase 2 * added support for EAP-TNC (Trusted Network Connect) (this version implements the EAP-TNC method and EAP-TTLS/EAP-FAST changes needed to run two methods in sequence (IF-T) and the IF-IMV and IF-TNCCS interfaces from TNCS) * added support for optional cryptobinding with PEAPv0 * added fragmentation support for EAP-TNC * added support for fragmenting EAP-TTLS/PEAP/FAST Phase 2 (tunneled) data * added support for opportunistic key caching (OKC) 2008-02-22 - v0.6.3 * fixed Reassociation Response callback processing when using internal MLME (driver_{hostap,nl80211,test}.c) * updated FT support to use the latest draft, IEEE 802.11r/D9.0 * copy optional Proxy-State attributes into RADIUS response when acting as a RADIUS authentication server * fixed EAPOL state machine to handle a case in which no response is received from the RADIUS authentication server; previous version could have triggered a crash in some cases after a timeout * fixed EAP-SIM/AKA realm processing to allow decorated usernames to be used * added a workaround for EAP-SIM/AKA peers that include incorrect null termination in the username * fixed EAP-SIM/AKA protected result indication to include AT_COUNTER attribute in notification messages only when using fast reauthentication * fixed EAP-SIM Start response processing for fast reauthentication case * added support for pending EAP processing in EAP-{PEAP,TTLS,FAST} phase 2 to allow EAP-SIM and EAP-AKA to be used as the Phase 2 method 2008-01-01 - v0.6.2 * fixed EAP-SIM and EAP-AKA message parser to validate attribute lengths properly to avoid potential crash caused by invalid messages * added data structure for storing allocated buffers (struct wpabuf); this does not affect hostapd usage, but many of the APIs changed and various interfaces (e.g., EAP) is not compatible with old versions * added support for protecting EAP-AKA/Identity messages with AT_CHECKCODE (optional feature in RFC 4187) * added support for protected result indication with AT_RESULT_IND for EAP-SIM and EAP-AKA (eap_sim_aka_result_ind=1) * added support for configuring EAP-TTLS phase 2 non-EAP methods in EAP server configuration; previously all four were enabled for every phase 2 user, now all four are disabled by default and need to be enabled with new method names TTLS-PAP, TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2 * removed old debug printing mechanism and the related 'debug' parameter in the configuration file; debug verbosity is now set with -d (or -dd) command line arguments * added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt); only shared key/password authentication is supported in this version 2007-11-24 - v0.6.1 * added experimental, integrated TLSv1 server implementation with the needed X.509/ASN.1/RSA/bignum processing (this can be enabled by setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in .config); this can be useful, e.g., if the target system does not have a suitable TLS library and a minimal code size is required * added support for EAP-FAST server method to the integrated EAP server * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest draft (draft-ietf-emu-eap-gpsk-07.txt) * added a new configuration parameter, rsn_pairwise, to allow different pairwise cipher suites to be enabled for WPA and RSN/WPA2 (note: if wpa_pairwise differs from rsn_pairwise, the driver will either need to support this or will have to use the WPA/RSN IEs from hostapd; currently, the included madwifi and bsd driver interfaces do not have support for this) * updated FT support to use the latest draft, IEEE 802.11r/D8.0 2007-05-28 - v0.6.0 * added experimental IEEE 802.11r/D6.0 support * updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48 * updated EAP-PSK to use the IANA-allocated EAP type 47 * fixed EAP-PSK bit ordering of the Flags field * fixed configuration reloading (SIGHUP) to re-initialize WPA PSKs by reading wpa_psk_file [Bug 181] * fixed EAP-TTLS AVP parser processing for too short AVP lengths * fixed IPv6 connection to RADIUS accounting server * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest draft (draft-ietf-emu-eap-gpsk-04.txt) * hlr_auc_gw: read GSM triplet file into memory and rotate through the entries instead of only using the same three triplets every time (this does not work properly with tests using multiple clients, but provides bit better triplet data for testing a single client; anyway, if a better quality triplets are needed, GSM-Milenage should be used instead of hardcoded triplet file) * fixed EAP-MSCHAPv2 server to use a space between S and M parameters in Success Request [Bug 203] * added support for sending EAP-AKA Notifications in error cases * updated to use IEEE 802.11w/D2.0 for management frame protection (still experimental) * RADIUS server: added support for processing duplicate messages (retransmissions from RADIUS client) by replying with the previous reply 2006-11-24 - v0.5.6 * added support for configuring and controlling multiple BSSes per radio interface (bss= in hostapd.conf); this is only available with Devicescape and test driver interfaces * fixed PMKSA cache update in the end of successful RSN pre-authentication * added support for dynamic VLAN configuration (i.e., selecting VLAN-ID for each STA based on RADIUS Access-Accept attributes); this requires VLAN support from the kernel driver/802.11 stack and this is currently only available with Devicescape and test driver interfaces * driver_madwifi: fixed configuration of unencrypted modes (plaintext and IEEE 802.1X without WEP) * removed STAKey handshake since PeerKey handshake has replaced it in IEEE 802.11ma and there are no known deployments of STAKey * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest draft (draft-ietf-emu-eap-gpsk-01.txt) * added preliminary implementation of IEEE 802.11w/D1.0 (management frame protection) (Note: this requires driver support to work properly.) (Note2: IEEE 802.11w is an unapproved draft and subject to change.) * hlr_auc_gw: added support for GSM-Milenage (for EAP-SIM) * hlr_auc_gw: added support for reading per-IMSI Milenage keys and parameters from a text file to make it possible to implement proper GSM/UMTS authentication server for multiple SIM/USIM cards using EAP-SIM/EAP-AKA * fixed session timeout processing with drivers that do not use ieee802_11.c (e.g., madwifi) 2006-08-27 - v0.5.5 * added 'hostapd_cli new_sta ' command for adding a new STA into hostapd (e.g., to initialize wired network authentication based on an external signal) * fixed hostapd to add PMKID KDE into 4-Way Handshake Message 1 when using WPA2 even if PMKSA caching is not used * added -P argument for hostapd to write the current process id into a file * added support for RADIUS Authentication Server MIB (RFC 2619) 2006-06-20 - v0.5.4 * fixed nt_password_hash build [Bug 144] * added PeerKey handshake implementation for IEEE 802.11e direct link setup (DLS) to replace STAKey handshake * added support for EAP Generalized Pre-Shared Key (EAP-GPSK, draft-clancy-emu-eap-shared-secret-00.txt) * fixed a segmentation fault when RSN pre-authentication was completed successfully [Bug 152] 2006-04-27 - v0.5.3 * do not build nt_password_hash and hlr_auc_gw by default to avoid requiring a TLS library for a successful build; these programs can be build with 'make nt_password_hash' and 'make hlr_auc_gw' * added a new configuration option, eapol_version, that can be used to set EAPOL version to 1 (default is 2) to work around broken client implementations that drop EAPOL frames which use version number 2 [Bug 89] * added support for EAP-SAKE (no EAP method number allocated yet, so this is using the same experimental type 255 as EAP-PSK) * fixed EAP-MSCHAPv2 message length validation 2006-03-19 - v0.5.2 * fixed stdarg use in hostapd_logger(): if both stdout and syslog logging was enabled, hostapd could trigger a segmentation fault in vsyslog on some CPU -- C library combinations * moved HLR/AuC gateway implementation for EAP-SIM/AKA into an external program to make it easier to use for implementing real SS7 gateway; eap_sim_db is not anymore used as a file name for GSM authentication triplets; instead, it is path to UNIX domain socket that will be used to communicate with the external gateway program (e.g., hlr_auc_gw) * added example HLR/AuC gateway implementation, hlr_auc_gw, that uses local information (GSM authentication triplets from a text file and hardcoded AKA authentication data); this can be used to test EAP-SIM and EAP-AKA * added Milenage algorithm (example 3GPP AKA algorithm) to hlr_auc_gw to make it possible to test EAP-AKA with real USIM cards (this is disabled by default; define AKA_USE_MILENAGE when building hlr_auc_gw to enable this) * driver_madwifi: added support for getting station RSN IE from madwifi-ng svn r1453 and newer; this fixes RSN that was apparently broken with earlier change (r1357) in the driver * changed EAP method registration to use a dynamic list of methods instead of a static list generated at build time * fixed WPA message 3/4 not to encrypt Key Data field (WPA IE) [Bug 125] * added ap_max_inactivity configuration parameter 2006-01-29 - v0.5.1 * driver_test: added better support for multiple APs and STAs by using a directory with sockets that include MAC address for each device in the name (test_socket=DIR:/tmp/test) * added support for EAP expanded type (vendor specific EAP methods) 2005-12-18 - v0.5.0 (beginning of 0.5.x development releases) * added experimental STAKey handshake implementation for IEEE 802.11e direct link setup (DLS); note: this is disabled by default in both build and runtime configuration (can be enabled with CONFIG_STAKEY=y and stakey=1) * added support for EAP methods to use callbacks to external programs by buffering a pending request and processing it after the EAP method is ready to continue * improved EAP-SIM database interface to allow external request to GSM HLR/AuC without blocking hostapd process * added support for using EAP-SIM pseudonyms and fast re-authentication * added support for EAP-AKA in the integrated EAP authenticator * added support for matching EAP identity prefixes (e.g., "1"*) in EAP user database to allow EAP-SIM/AKA selection without extra roundtrip for EAP-Nak negotiation * added support for storing EAP user password as NtPasswordHash instead of plaintext password when using MSCHAP or MSCHAPv2 for authentication (hash:<16-octet hex value>); added nt_password_hash tool for hashing password to generate NtPasswordHash 2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases) * driver_wired: fixed EAPOL sending to optionally use PAE group address as the destination instead of supplicant MAC address; this is disabled by default, but should be enabled with use_pae_group_addr=1 in configuration file if the wired interface is used by only one device at the time (common switch configuration) * driver_madwifi: configure driver to use TKIP countermeasures in order to get correct behavior (IEEE 802.11 association failing; previously, association succeeded, but hostpad forced disassociation immediately) * driver_madwifi: added support for madwifi-ng 2005-10-27 - v0.4.6 * added support for replacing user identity from EAP with RADIUS User-Name attribute from Access-Accept message, if that is included, for the RADIUS accounting messages (e.g., for EAP-PEAP/TTLS to get tunneled identity into accounting messages when the RADIUS server does not support better way of doing this with Class attribute) * driver_madwifi: fixed EAPOL packet receive for configuration where ath# is part of a bridge interface * added a configuration file and log analyzer script for logwatch * fixed EAPOL state machine step function to process all state transitions before processing new events; this resolves a race condition in which EAPOL-Start message could trigger hostapd to send two EAP-Response/Identity frames to the authentication server 2005-09-25 - v0.4.5 * added client CA list to the TLS certificate request in order to make it easier for the client to select which certificate to use * added experimental support for EAP-PSK * added support for WE-19 (hostap, madwifi) 2005-08-21 - v0.4.4 * fixed build without CONFIG_RSN_PREAUTH * fixed FreeBSD build 2005-06-26 - v0.4.3 * fixed PMKSA caching to copy User-Name and Class attributes so that RADIUS accounting gets correct information * start RADIUS accounting only after successful completion of WPA 4-Way Handshake if WPA-PSK is used * fixed PMKSA caching for the case where STA (re)associates without first disassociating 2005-06-12 - v0.4.2 * EAP-PAX is now registered as EAP type 46 * fixed EAP-PAX MAC calculation * fixed EAP-PAX CK and ICK key derivation * renamed eap_authenticator configuration variable to eap_server to better match with RFC 3748 (EAP) terminology * driver_test: added support for testing hostapd with wpa_supplicant by using test driver interface without any kernel drivers or network cards 2005-05-22 - v0.4.1 * fixed RADIUS server initialization when only auth or acct server is configured and the other one is left empty * driver_madwifi: added support for RADIUS accounting * driver_madwifi: added preliminary support for compiling against 'BSD' branch of madwifi CVS tree * driver_madwifi: fixed pairwise key removal to allow WPA reauth without disassociation * added support for reading additional certificates from PKCS#12 files and adding them to the certificate chain * fixed RADIUS Class attribute processing to only use Access-Accept packets to update Class; previously, other RADIUS authentication packets could have cleared Class attribute * added support for more than one Class attribute in RADIUS packets * added support for verifying certificate revocation list (CRL) when using integrated EAP authenticator for EAP-TLS; new hostapd.conf options 'check_crl'; CRL must be included in the ca_cert file for now 2005-04-25 - v0.4.0 (beginning of 0.4.x development releases) * added support for including network information into EAP-Request/Identity message (ASCII-0 (nul) in eap_message) (e.g., to implement draft-adrange-eap-network-discovery-07.txt) * fixed a bug which caused some RSN pre-authentication cases to use freed memory and potentially crash hostapd * fixed private key loading for cases where passphrase is not set * added support for sending TLS alerts and aborting authentication when receiving a TLS alert * fixed WPA2 to add PMKSA cache entry when using integrated EAP authenticator * fixed PMKSA caching (EAP authentication was not skipped correctly with the new state machine changes from IEEE 802.1X draft) * added support for RADIUS over IPv6; own_ip_addr, auth_server_addr, and acct_server_addr can now be IPv6 addresses (CONFIG_IPV6=y needs to be added to .config to include IPv6 support); for RADIUS server, radius_server_ipv6=1 needs to be set in hostapd.conf and addresses in RADIUS clients file can then use IPv6 format * added experimental support for EAP-PAX * replaced hostapd control interface library (hostapd_ctrl.[ch]) with the same implementation that wpa_supplicant is using (wpa_ctrl.[ch]) 2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) 2005-01-23 - v0.3.5 * added support for configuring a forced PEAP version based on the Phase 1 identity * fixed PEAPv1 to use tunneled EAP-Success/Failure instead of EAP-TLV to terminate authentication * fixed EAP identifier duplicate processing with the new IEEE 802.1X draft * clear accounting data in the driver when starting a new accounting session * driver_madwifi: filter wireless events based on ifindex to allow more than one network interface to be used * fixed WPA message 2/4 processing not to cancel timeout for TimeoutEvt setting if the packet does not pass MIC verification (e.g., due to incorrect PSK); previously, message 1/4 was not tried again if an invalid message 2/4 was received * fixed reconfiguration of RADIUS client retransmission timer when adding a new message to the pending list; previously, timer was not updated at this point and if there was a pending message with long time for the next retry, the new message needed to wait that long for its first retry, too 2005-01-09 - v0.3.4 * added support for configuring multiple allowed EAP types for Phase 2 authentication (EAP-PEAP, EAP-TTLS) * fixed EAPOL-Start processing to trigger WPA reauthentication (previously, only EAPOL authentication was done) 2005-01-02 - v0.3.3 * added support for EAP-PEAP in the integrated EAP authenticator * added support for EAP-GTC in the integrated EAP authenticator * added support for configuring list of EAP methods for Phase 1 so that the integrated EAP authenticator can, e.g., use the wildcard entry for EAP-TLS and EAP-PEAP * added support for EAP-TTLS in the integrated EAP authenticator * added support for EAP-SIM in the integrated EAP authenticator * added support for using hostapd as a RADIUS authentication server with the integrated EAP authenticator taking care of EAP authentication (new hostapd.conf options: radius_server_clients and radius_server_auth_port); this is not included in default build; use CONFIG_RADIUS_SERVER=y in .config to include 2004-12-19 - v0.3.2 * removed 'daemonize' configuration file option since it has not really been used at all for more than year * driver_madwifi: fixed group key setup and added get_ssid method * added support for EAP-MSCHAPv2 in the integrated EAP authenticator 2004-12-12 - v0.3.1 * added support for integrated EAP-TLS authentication (new hostapd.conf variables: ca_cert, server_cert, private_key, private_key_passwd); this enabled dynamic keying (WPA2/WPA/IEEE 802.1X/WEP) without external RADIUS server * added support for reading PKCS#12 (PFX) files (as a replacement for PEM/DER) to get certificate and private key (CONFIG_PKCS12) 2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) * added support for Acct-{Input,Output}-Gigawords * added support for Event-Timestamp (in RADIUS Accounting-Requests) * added support for RADIUS Authentication Client MIB (RFC2618) * added support for RADIUS Accounting Client MIB (RFC2620) * made EAP re-authentication period configurable (eap_reauth_period) * fixed EAPOL reauthentication to trigger WPA/WPA2 reauthentication * fixed EAPOL state machine to stop if STA is removed during eapol_sm_step(); this fixes at least one segfault triggering bug with IEEE 802.11i pre-authentication * added support for multiple WPA pre-shared keys (e.g., one for each client MAC address or keys shared by a group of clients); new hostapd.conf field wpa_psk_file for setting path to a text file containing PSKs, see hostapd.wpa_psk for an example * added support for multiple driver interfaces to allow hostapd to be used with other drivers * added wired authenticator driver interface (driver=wired in hostapd.conf, see wired.conf for example configuration) * added madwifi driver interface (driver=madwifi in hostapd.conf, see madwifi.conf for example configuration; Note: include files from madwifi project is needed for building and a configuration file, .config, needs to be created in hostapd directory with CONFIG_DRIVER_MADWIFI=y to include this driver interface in hostapd build) * fixed an alignment issue that could cause SHA-1 to fail on some platforms (e.g., Intel ixp425 with a compiler that does not 32-bit align variables) * fixed RADIUS reconnection after an error in sending interim accounting packets * added hostapd control interface for external programs and an example CLI, hostapd_cli (like wpa_cli for wpa_supplicant) * started adding dot11, dot1x, radius MIBs ('hostapd_cli mib', 'hostapd_cli sta ') * finished update from IEEE 802.1X-2001 to IEEE 802.1X-REV (now d11) * added support for strict GTK rekeying (wpa_strict_rekey in hostapd.conf) * updated IAPP to use UDP port 3517 and multicast address 224.0.1.178 (instead of broadcast) for IAPP ADD-notify (moved from draft 3 to IEEE 802.11F-2003) * added Prism54 driver interface (driver=prism54 in hostapd.conf; note: .config needs to be created in hostapd directory with CONFIG_DRIVER_PRISM54=y to include this driver interface in hostapd build) * dual-licensed hostapd (GPLv2 and BSD licenses) * fixed RADIUS accounting to generate a new session id for cases where a station reassociates without first being complete deauthenticated * fixed STA disassociation handler to mark next timeout state to deauthenticate the station, i.e., skip long wait for inactivity poll and extra disassociation, if the STA disassociates without deauthenticating * added integrated EAP authenticator that can be used instead of external RADIUS authentication server; currently, only EAP-MD5 is supported, so this cannot yet be used for key distribution; the EAP method interface is generic, though, so adding new EAP methods should be straightforward; new hostapd.conf variables: 'eap_authenticator' and 'eap_user_file'; this obsoletes "minimal authentication server" ('minimal_eap' in hostapd.conf) which is now removed * added support for FreeBSD and driver interface for the BSD net80211 layer (driver=bsd in hostapd.conf and CONFIG_DRIVER_BSD=y in .config); please note that some of the required kernel mods have not yet been committed 2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) * fixed some accounting cases where Accounting-Start was sent when IEEE 802.1X port was being deauthorized 2004-06-20 - v0.2.3 * modified RADIUS client to re-connect the socket in case of certain error codes that are generated when a network interface state is changes (e.g., when IP address changes or the interface is set UP) * fixed couple of cases where EAPOL state for a station was freed twice causing a segfault for hostapd * fixed couple of bugs in processing WPA deauthentication (freed data was used) 2004-05-31 - v0.2.2 * fixed WPA/WPA2 group rekeying to use key index correctly (GN/GM) * fixed group rekeying to send zero TSC in EAPOL-Key messages to fix cases where STAs dropped multicast frames as replay attacks * added support for copying RADIUS Attribute 'Class' from authentication messages into accounting messages * send canned EAP failure if RADIUS server sends Access-Reject without EAP message (previously, Supplicant was not notified in this case) * fixed mixed WPA-PSK and WPA-EAP mode to work with WPA-PSK (i.e., do not start EAPOL state machines if the STA selected to use WPA-PSK) 2004-05-06 - v0.2.1 * added WPA and IEEE 802.11i/RSN (WPA2) Authenticator functionality - based on IEEE 802.11i/D10.0 but modified to interoperate with WPA (i.e., IEEE 802.11i/D3.0) - supports WPA-only, RSN-only, and mixed WPA/RSN mode - both WPA-PSK and WPA-RADIUS/EAP are supported - PMKSA caching and pre-authentication - new hostapd.conf variables: wpa, wpa_psk, wpa_passphrase, wpa_key_mgmt, wpa_pairwise, wpa_group_rekey, wpa_gmk_rekey, rsn_preauth, rsn_preauth_interfaces * fixed interim accounting to remove any pending accounting messages to the STA before sending a new one 2004-02-15 - v0.2.0 * added support for Acct-Interim-Interval: - draft-ietf-radius-acct-interim-01.txt - use Acct-Interim-Interval attribute from Access-Accept if local 'radius_acct_interim_interval' is not set - allow different update intervals for each STA * fixed event loop to call signal handlers only after returning from the real signal handler * reset sta->timeout_next after successful association to make sure that the previously registered inactivity timer will not remove the STA immediately (e.g., if STA deauthenticates and re-associates before the timer is triggered). * added new hostapd.conf variable, nas_identifier, that can be used to add an optional RADIUS Attribute, NAS-Identifier, into authentication and accounting messages * added support for Accounting-On and Accounting-Off messages * fixed accounting session handling to send Accounting-Start only once per session and not to send Accounting-Stop if the session was not initialized properly * fixed Accounting-Stop statistics in cases where the message was previously sent after the kernel entry for the STA (and/or IEEE 802.1X data) was removed Note: Older changes up to and including v0.1.0 are included in the ChangeLog of the Host AP driver. diff --git a/contrib/wpa/hostapd/README b/contrib/wpa/hostapd/README index 1f30d7ea39fa..739c964d44d8 100644 --- a/contrib/wpa/hostapd/README +++ b/contrib/wpa/hostapd/README @@ -1,354 +1,354 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator and RADIUS authentication server ================================================================ -Copyright (c) 2002-2019, Jouni Malinen and contributors +Copyright (c) 2002-2022, Jouni Malinen and contributors All Rights Reserved. This program is licensed under the BSD license (the one with advertisement clause removed). If you are submitting changes to the project, please see CONTRIBUTIONS file for more instructions. License ------- This software may be distributed, used, and modified under the terms of BSD license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name(s) of the above-listed copyright holder(s) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Introduction ============ Originally, hostapd was an optional user space component for Host AP driver. It adds more features to the basic IEEE 802.11 management included in the kernel driver: using external RADIUS authentication server for MAC address based access control, IEEE 802.1X Authenticator and dynamic WEP keying, RADIUS accounting, WPA/WPA2 (IEEE 802.11i/RSN) Authenticator and dynamic TKIP/CCMP keying. The current version includes support for other drivers, an integrated EAP server (i.e., allow full authentication without requiring an external RADIUS authentication server), and RADIUS authentication server for EAP authentication. Requirements ------------ Current hardware/software requirements: - drivers: Host AP driver for Prism2/2.5/3. (http://w1.fi/hostap-driver.html) Please note that station firmware version needs to be 1.7.0 or newer to work in WPA mode. mac80211-based drivers that support AP mode (with driver=nl80211). This includes drivers for Atheros (ath9k) and Broadcom (b43) chipsets. Any wired Ethernet driver for wired IEEE 802.1X authentication (experimental code) FreeBSD -current BSD net80211 layer (e.g., Atheros driver) Build configuration ------------------- In order to be able to build hostapd, you will need to create a build time configuration file, .config that selects which optional components are included. See defconfig file for example configuration and list of available options. IEEE 802.1X =========== IEEE Std 802.1X-2001 is a standard for port-based network access control. In case of IEEE 802.11 networks, a "virtual port" is used between each associated station and the AP. IEEE 802.11 specifies minimal authentication mechanism for stations, whereas IEEE 802.1X introduces a extensible mechanism for authenticating and authorizing users. IEEE 802.1X uses elements called Supplicant, Authenticator, Port Access Entity, and Authentication Server. Supplicant is a component in a station and it performs the authentication with the Authentication Server. An access point includes an Authenticator that relays the packets between a Supplicant and an Authentication Server. In addition, it has a Port Access Entity (PAE) with Authenticator functionality for controlling the virtual port authorization, i.e., whether to accept packets from or to the station. IEEE 802.1X uses Extensible Authentication Protocol (EAP). The frames between a Supplicant and an Authenticator are sent using EAP over LAN (EAPOL) and the Authenticator relays these frames to the Authentication Server (and similarly, relays the messages from the Authentication Server to the Supplicant). The Authentication Server can be colocated with the Authenticator, in which case there is no need for additional protocol for EAP frame transmission. However, a more common configuration is to use an external Authentication Server and encapsulate EAP frame in the frames used by that server. RADIUS is suitable for this, but IEEE 802.1X would also allow other mechanisms. Host AP driver includes PAE functionality in the kernel driver. It is a relatively simple mechanism for denying normal frames going to or coming from an unauthorized port. PAE allows IEEE 802.1X related frames to be passed between the Supplicant and the Authenticator even on an unauthorized port. User space daemon, hostapd, includes Authenticator functionality. It receives 802.1X (EAPOL) frames from the Supplicant using the wlan#ap device that is also used with IEEE 802.11 management frames. The frames to the Supplicant are sent using the same device. The normal configuration of the Authenticator would use an external Authentication Server. hostapd supports RADIUS encapsulation of EAP packets, so the Authentication Server should be a RADIUS server, like FreeRADIUS (http://www.freeradius.org/). The Authenticator in hostapd relays the frames between the Supplicant and the Authentication Server. It also controls the PAE functionality in the kernel driver by controlling virtual port authorization, i.e., station-AP connection, based on the IEEE 802.1X state. When a station would like to use the services of an access point, it will first perform IEEE 802.11 authentication. This is normally done with open systems authentication, so there is no security. After this, IEEE 802.11 association is performed. If IEEE 802.1X is configured to be used, the virtual port for the station is set in Unauthorized state and only IEEE 802.1X frames are accepted at this point. The Authenticator will then ask the Supplicant to authenticate with the Authentication Server. After this is completed successfully, the virtual port is set to Authorized state and frames from and to the station are accepted. Host AP configuration for IEEE 802.1X ------------------------------------- The user space daemon has its own configuration file that can be used to define AP options. Distribution package contains an example configuration file (hostapd/hostapd.conf) that can be used as a basis for configuration. It includes examples of all supported configuration options and short description of each option. hostapd should be started with full path to the configuration file as the command line argument, e.g., './hostapd /etc/hostapd.conf'. If you have more that one wireless LAN card, you can use one hostapd process for multiple interfaces by giving a list of configuration files (one per interface) in the command line. hostapd includes a minimal co-located IEEE 802.1X server which can be used to test IEEE 802.1X authentication. However, it should not be used in normal use since it does not provide any security. This can be configured by setting ieee8021x and minimal_eap options in the configuration file. An external Authentication Server (RADIUS) is configured with auth_server_{addr,port,shared_secret} options. In addition, ieee8021x and own_ip_addr must be set for this mode. With such configuration, the co-located Authentication Server is not used and EAP frames will be relayed using EAPOL between the Supplicant and the Authenticator and RADIUS encapsulation between the Authenticator and the Authentication Server. Other than this, the functionality is similar to the case with the co-located Authentication Server. Authentication Server --------------------- Any RADIUS server supporting EAP should be usable as an IEEE 802.1X Authentication Server with hostapd Authenticator. FreeRADIUS (http://www.freeradius.org/) has been successfully tested with hostapd Authenticator. Automatic WEP key configuration ------------------------------- EAP/TLS generates a session key that can be used to send WEP keys from an AP to authenticated stations. The Authenticator in hostapd can be configured to automatically select a random default/broadcast key (shared by all authenticated stations) with wep_key_len_broadcast option (5 for 40-bit WEP or 13 for 104-bit WEP). In addition, wep_key_len_unicast option can be used to configure individual unicast keys for stations. This requires support for individual keys in the station driver. WEP keys can be automatically updated by configuring rekeying. This will improve security of the network since same WEP key will only be used for a limited period of time. wep_rekey_period option sets the interval for rekeying in seconds. WPA/WPA2 ======== Features -------- Supported WPA/IEEE 802.11i features: - WPA-PSK ("WPA-Personal") - WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") - key management for CCMP, TKIP, WEP104, WEP40 - RSN/WPA2 (IEEE 802.11i), including PMKSA caching and pre-authentication WPA --- The original security mechanism of IEEE 802.11 standard was not designed to be strong and has proved to be insufficient for most networks that require some kind of security. Task group I (Security) of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked to address the flaws of the base standard and has in practice completed its work in May 2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was approved in June 2004 and this amendment was published in July 2004. Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the IEEE 802.11i work (draft 3.0) to define a subset of the security enhancements that can be implemented with existing wlan hardware. This is called Wi-Fi Protected Access (WPA). This has now become a mandatory component of interoperability testing and certification done by Wi-Fi Alliance. IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm for protecting wireless networks. WEP uses RC4 with 40-bit keys, 24-bit initialization vector (IV), and CRC32 to protect against packet forgery. All these choices have proven to be insufficient: key space is too small against current attacks, RC4 key scheduling is insufficient (beginning of the pseudorandom stream should be skipped), IV space is too small and IV reuse makes attacks easier, there is no replay protection, and non-keyed authentication does not protect against bit flipping packet data. WPA is an intermediate solution for the security issues. It uses Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a compromise on strong security and possibility to use existing hardware. It still uses RC4 for the encryption like WEP, but with per-packet RC4 keys. In addition, it implements replay protection, keyed packet authentication mechanism (Michael MIC). Keys can be managed using two different mechanisms. WPA can either use an external authentication server (e.g., RADIUS) and EAP just like IEEE 802.1X is using or pre-shared keys without need for additional servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal", respectively. Both mechanisms will generate a master session key for the Authenticator (AP) and Supplicant (client station). WPA implements a new key handshake (4-Way Handshake and Group Key Handshake) for generating and exchanging data encryption keys between the Authenticator and Supplicant. This handshake is also used to verify that both Authenticator and Supplicant know the master session key. These handshakes are identical regardless of the selected key management mechanism (only the method for generating master session key changes). IEEE 802.11i / WPA2 ------------------- The design for parts of IEEE 802.11i that were not included in WPA has finished (May 2004) and this amendment to IEEE 802.11 was approved in June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new version of WPA called WPA2. This includes, e.g., support for more robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC) to replace TKIP and optimizations for handoff (reduced number of messages in initial key handshake, pre-authentication, and PMKSA caching). Some wireless LAN vendors are already providing support for CCMP in their WPA products. There is no "official" interoperability certification for CCMP and/or mixed modes using both TKIP and CCMP, so some interoperability issues can be expected even though many combinations seem to be working with equipment from different vendors. Testing for WPA2 is likely to start during the second half of 2004. hostapd configuration for WPA/WPA2 ---------------------------------- TODO # Enable WPA. Setting this variable configures the AP to require WPA (either # WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either # wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. # For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), # RADIUS authentication server must be configured, and WPA-EAP must be included # in wpa_key_mgmt. # This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) # and/or WPA2 (full IEEE 802.11i/RSN): # bit0 = WPA # bit1 = IEEE 802.11i/RSN (WPA2) #wpa=1 # WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit # secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase # (8..63 characters) that will be converted to PSK. This conversion uses SSID # so the PSK changes when ASCII passphrase is used and the SSID is changed. #wpa_psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef #wpa_passphrase=secret passphrase # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The # entries are separated with a space. #wpa_key_mgmt=WPA-PSK WPA-EAP # Set of accepted cipher suites (encryption algorithms) for pairwise keys # (unicast packets). This is a space separated list of algorithms: # CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i] # TKIP = Temporal Key Integrity Protocol [IEEE 802.11i] # Group cipher suite (encryption algorithm for broadcast and multicast frames) # is automatically selected based on this configuration. If only CCMP is # allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, # TKIP will be used as the group cipher. #wpa_pairwise=TKIP CCMP # Time interval for rekeying GTK (broadcast/multicast encryption keys) in # seconds. #wpa_group_rekey=600 # Time interval for rekeying GMK (master key used internally to generate GTKs # (in seconds). #wpa_gmk_rekey=86400 # Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up # roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN # authentication and key handshake before actually associating with a new AP. #rsn_preauth=1 # # Space separated list of interfaces from which pre-authentication frames are # accepted (e.g., 'eth0' or 'eth0 wlan0wds0'. This list should include all # interface that are used for connections to other APs. This could include # wired interfaces and WDS links. The normal wireless data interface towards # associated stations (e.g., wlan0) should not be added, since # pre-authentication is only used with APs other than the currently associated # one. #rsn_preauth_interfaces=eth0 diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c index 0e7fdd6bccfb..2609121116b5 100644 --- a/contrib/wpa/hostapd/hostapd_cli.c +++ b/contrib/wpa/hostapd/hostapd_cli.c @@ -1,2197 +1,2197 @@ /* * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2019, Jouni Malinen + * Copyright (c) 2004-2022, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" #include #include "common/wpa_ctrl.h" #include "common/ieee802_11_defs.h" #include "utils/common.h" #include "utils/eloop.h" #include "utils/edit.h" #include "common/version.h" #include "common/cli.h" #ifndef CONFIG_NO_CTRL_IFACE static const char *const hostapd_cli_version = "hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2019, Jouni Malinen and contributors"; +"Copyright (c) 2004-2022, Jouni Malinen and contributors"; static struct wpa_ctrl *ctrl_conn; static int hostapd_cli_quit = 0; static int hostapd_cli_attached = 0; #ifndef CONFIG_CTRL_IFACE_DIR #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd" #endif /* CONFIG_CTRL_IFACE_DIR */ static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR; static const char *client_socket_dir = NULL; static char *ctrl_ifname = NULL; static const char *pid_file = NULL; static const char *action_file = NULL; static int ping_interval = 5; static int interactive = 0; static int event_handler_registered = 0; static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */ static void print_help(FILE *stream, const char *cmd); static char ** list_cmd_list(void); static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx); static void update_stations(struct wpa_ctrl *ctrl); static void cli_event(const char *str); static void usage(void) { fprintf(stderr, "%s\n", hostapd_cli_version); fprintf(stderr, "\n" "usage: hostapd_cli [-p] [-i] [-hvBr] " "[-a] \\\n" " [-P] [-G] [command..]\n" "\n" "Options:\n" " -h help (show this usage text)\n" " -v shown version information\n" " -p path to find control sockets (default: " "/var/run/hostapd)\n" " -s dir path to open client sockets (default: " CONFIG_CTRL_IFACE_DIR ")\n" " -a run in daemon mode executing the action file " "based on events\n" " from hostapd\n" " -r try to reconnect when client socket is " "disconnected.\n" " This is useful only when used with -a.\n" " -B run a daemon in the background\n" " -i Interface to listen on (default: first " "interface found in the\n" " socket path)\n\n"); print_help(stderr, NULL); } static void register_event_handler(struct wpa_ctrl *ctrl) { if (!ctrl_conn) return; if (interactive) { event_handler_registered = !eloop_register_read_sock(wpa_ctrl_get_fd(ctrl), hostapd_cli_receive, NULL, NULL); } } static void unregister_event_handler(struct wpa_ctrl *ctrl) { if (!ctrl_conn) return; if (interactive && event_handler_registered) { eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl)); event_handler_registered = 0; } } static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname) { #ifndef CONFIG_CTRL_IFACE_UDP char *cfile; int flen; #endif /* !CONFIG_CTRL_IFACE_UDP */ if (ifname == NULL) return NULL; #ifdef CONFIG_CTRL_IFACE_UDP ctrl_conn = wpa_ctrl_open(ifname); return ctrl_conn; #else /* CONFIG_CTRL_IFACE_UDP */ flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2; cfile = malloc(flen); if (cfile == NULL) return NULL; snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); if (client_socket_dir && client_socket_dir[0] && access(client_socket_dir, F_OK) < 0) { perror(client_socket_dir); free(cfile); return NULL; } ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir); free(cfile); return ctrl_conn; #endif /* CONFIG_CTRL_IFACE_UDP */ } static void hostapd_cli_close_connection(void) { if (ctrl_conn == NULL) return; unregister_event_handler(ctrl_conn); if (hostapd_cli_attached) { wpa_ctrl_detach(ctrl_conn); hostapd_cli_attached = 0; } wpa_ctrl_close(ctrl_conn); ctrl_conn = NULL; } static int hostapd_cli_reconnect(const char *ifname) { char *next_ctrl_ifname; hostapd_cli_close_connection(); if (!ifname) return -1; next_ctrl_ifname = os_strdup(ifname); os_free(ctrl_ifname); ctrl_ifname = next_ctrl_ifname; if (!ctrl_ifname) return -1; ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); if (!ctrl_conn) return -1; if (!interactive && !action_file) return 0; if (wpa_ctrl_attach(ctrl_conn) == 0) { hostapd_cli_attached = 1; register_event_handler(ctrl_conn); update_stations(ctrl_conn); } else { printf("Warning: Failed to attach to hostapd.\n"); } return 0; } static void hostapd_cli_msg_cb(char *msg, size_t len) { cli_event(msg); printf("%s\n", msg); } static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print) { char buf[4096]; size_t len; int ret; if (ctrl_conn == NULL) { printf("Not connected to hostapd - command dropped.\n"); return -1; } len = sizeof(buf) - 1; ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, hostapd_cli_msg_cb); if (ret == -2) { printf("'%s' command timed out.\n", cmd); return -2; } else if (ret < 0) { printf("'%s' command failed.\n", cmd); return -1; } if (print) { buf[len] = '\0'; printf("%s", buf); } return 0; } static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) { return _wpa_ctrl_command(ctrl, cmd, 1); } static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, int argc, char *argv[]) { char buf[4096]; if (argc < min_args) { printf("Invalid %s command - at least %d argument%s required.\n", cmd, min_args, min_args > 1 ? "s are" : " is"); return -1; } if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "PING"); } static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "RELOG"); } static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) { if (argc > 0 && os_strcmp(argv[0], "driver") == 0) return wpa_ctrl_command(ctrl, "STATUS-DRIVER"); return wpa_ctrl_command(ctrl, "STATUS"); } static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) { if (argc > 0) { char buf[100]; os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } return wpa_ctrl_command(ctrl, "MIB"); } static int hostapd_cli_exec(const char *program, const char *arg1, const char *arg2) { char *arg; size_t len; int res; len = os_strlen(arg1) + os_strlen(arg2) + 2; arg = os_malloc(len); if (arg == NULL) return -1; os_snprintf(arg, len, "%s %s", arg1, arg2); res = os_exec(program, arg, 1); os_free(arg); return res; } static void hostapd_cli_action_process(char *msg, size_t len) { const char *pos; pos = msg; if (*pos == '<') { pos = os_strchr(pos, '>'); if (pos) pos++; else pos = msg; } hostapd_cli_exec(action_file, ctrl_ifname, pos); } static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc < 1) { printf("Invalid 'sta' command - at least one argument, STA " "address, is required.\n"); return -1; } if (argc > 1) snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]); else snprintf(buf, sizeof(buf), "STA %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } static char ** hostapd_complete_stations(const char *str, int pos) { int arg = get_cmd_arg_num(str, pos); char **res = NULL; switch (arg) { case 1: res = cli_txt_list_array(&stations); break; } return res; } static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc != 1) { printf("Invalid 'new_sta' command - exactly one argument, STA " "address, is required.\n"); return -1; } snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc < 1) { printf("Invalid 'deauthenticate' command - exactly one " "argument, STA address, is required.\n"); return -1; } if (argc > 1) os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s", argv[0], argv[1]); else os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc < 1) { printf("Invalid 'disassociate' command - exactly one " "argument, STA address, is required.\n"); return -1; } if (argc > 1) os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s", argv[0], argv[1]); else os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } #ifdef CONFIG_TAXONOMY static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc != 1) { printf("Invalid 'signature' command - exactly one argument, STA address, is required.\n"); return -1; } os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } #endif /* CONFIG_TAXONOMY */ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc != 1) { printf("Invalid 'sa_query' command - exactly one argument, " "STA address, is required.\n"); return -1; } snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } #ifdef CONFIG_WPS static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[256]; if (argc < 2) { printf("Invalid 'wps_pin' command - at least two arguments, " "UUID and PIN, are required.\n"); return -1; } if (argc > 3) snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s", argv[0], argv[1], argv[2], argv[3]); else if (argc > 2) snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s", argv[0], argv[1], argv[2]); else snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]); return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; if (argc != 1 && argc != 2) { printf("Invalid WPS_CHECK_PIN command: needs one argument:\n" "- PIN to be verified\n"); return -1; } if (argc == 2) res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s", argv[0], argv[1]); else res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s", argv[0]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long WPS_CHECK_PIN command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "WPS_PBC"); } static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "WPS_CANCEL"); } #ifdef CONFIG_WPS_NFC static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc, char *argv[]) { int ret; char *buf; size_t buflen; if (argc != 1) { printf("Invalid 'wps_nfc_tag_read' command - one argument " "is required.\n"); return -1; } buflen = 18 + os_strlen(argv[0]); buf = os_malloc(buflen); if (buf == NULL) return -1; os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]); ret = wpa_ctrl_command(ctrl, buf); os_free(buf); return ret; } static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[64]; int res; if (argc != 1) { printf("Invalid 'wps_nfc_config_token' command - one argument " "is required.\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s", argv[0]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long WPS_NFC_CONFIG_TOKEN command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[64]; int res; if (argc != 1) { printf("Invalid 'wps_nfc_token' command - one argument is " "required.\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long WPS_NFC_TOKEN command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[64]; int res; if (argc != 2) { printf("Invalid 'nfc_get_handover_sel' command - two arguments " "are required.\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s", argv[0], argv[1]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long NFC_GET_HANDOVER_SEL command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } #endif /* CONFIG_WPS_NFC */ static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; if (argc < 1) { printf("Invalid 'wps_ap_pin' command - at least one argument " "is required.\n"); return -1; } if (argc > 2) snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s", argv[0], argv[1], argv[2]); else if (argc > 1) snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s", argv[0], argv[1]); else snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]); return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "WPS_GET_STATUS"); } static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[256]; char ssid_hex[2 * SSID_MAX_LEN + 1]; char key_hex[2 * 64 + 1]; int i; if (argc < 1) { printf("Invalid 'wps_config' command - at least two arguments " "are required.\n"); return -1; } ssid_hex[0] = '\0'; for (i = 0; i < SSID_MAX_LEN; i++) { if (argv[0][i] == '\0') break; os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]); } key_hex[0] = '\0'; if (argc > 3) { for (i = 0; i < 64; i++) { if (argv[3][i] == '\0') break; os_snprintf(&key_hex[i * 2], 3, "%02x", argv[3][i]); } } if (argc > 3) snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s", ssid_hex, argv[1], argv[2], key_hex); else if (argc > 2) snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s", ssid_hex, argv[1], argv[2]); else snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s", ssid_hex, argv[1]); return wpa_ctrl_command(ctrl, buf); } #endif /* CONFIG_WPS */ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[300]; int res; if (argc < 2) { printf("Invalid 'disassoc_imminent' command - two arguments " "(STA addr and Disassociation Timer) are needed\n"); return -1; } res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s", argv[0], argv[1]); if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[300]; int res; if (argc < 3) { printf("Invalid 'ess_disassoc' command - three arguments (STA " "addr, disassoc timer, and URL) are needed\n"); return -1; } res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s", argv[0], argv[1], argv[2]); if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[2000], *tmp; int res, i, total; if (argc < 1) { printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n"); return -1; } res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]); if (os_snprintf_error(sizeof(buf), res)) return -1; total = res; for (i = 1; i < argc; i++) { tmp = &buf[total]; res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]); if (os_snprintf_error(sizeof(buf) - total, res)) return -1; total += res; } return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "GET_CONFIG"); } static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd, char *addr, size_t addr_len, int print) { char buf[4096], *pos; size_t len; int ret; if (ctrl_conn == NULL) { printf("Not connected to hostapd - command dropped.\n"); return -1; } len = sizeof(buf) - 1; ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, hostapd_cli_msg_cb); if (ret == -2) { printf("'%s' command timed out.\n", cmd); return -2; } else if (ret < 0) { printf("'%s' command failed.\n", cmd); return -1; } buf[len] = '\0'; if (memcmp(buf, "FAIL", 4) == 0) return -1; if (print) printf("%s", buf); pos = buf; while (*pos != '\0' && *pos != '\n') pos++; *pos = '\0'; os_strlcpy(addr, buf, addr_len); return 0; } static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char addr[32], cmd[64]; if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1)) return 0; do { snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0); return -1; } static int hostapd_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char addr[32], cmd[64]; if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0)) return 0; do { if (os_strcmp(addr, "") != 0) printf("%s\n", addr); os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0); return 0; } static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) { print_help(stdout, argc > 0 ? argv[0] : NULL); return 0; } static char ** hostapd_cli_complete_help(const char *str, int pos) { int arg = get_cmd_arg_num(str, pos); char **res = NULL; switch (arg) { case 1: res = list_cmd_list(); break; } return res; } static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) { printf("%s\n\n%s\n", hostapd_cli_version, cli_full_license); return 0; } static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[200]; int res; if (argc != 1) { printf("Invalid 'set_qos_map_set' command - " "one argument (comma delimited QoS map set) " "is needed\n"); return -1; } res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]); if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[50]; int res; if (argc != 1) { printf("Invalid 'send_qos_map_conf' command - " "one argument (STA addr) is needed\n"); return -1; } res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]); if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[300]; int res; if (argc < 2) { printf("Invalid 'hs20_wnm_notif' command - two arguments (STA " "addr and URL) are needed\n"); return -1; } res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s", argv[0], argv[1]); if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[300]; int res; if (argc < 3) { printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n"); return -1; } if (argc > 3) res = os_snprintf(buf, sizeof(buf), "HS20_DEAUTH_REQ %s %s %s %s", argv[0], argv[1], argv[2], argv[3]); else res = os_snprintf(buf, sizeof(buf), "HS20_DEAUTH_REQ %s %s %s", argv[0], argv[1], argv[2]); if (os_snprintf_error(sizeof(buf), res)) return -1; return wpa_ctrl_command(ctrl, buf); } static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) { hostapd_cli_quit = 1; if (interactive) eloop_terminate(); return 0; } static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; if (argc != 1) { printf("Invalid LEVEL command: needs one argument (debug " "level)\n"); return 0; } snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); return wpa_ctrl_command(ctrl, cmd); } static void update_stations(struct wpa_ctrl *ctrl) { char addr[32], cmd[64]; if (!ctrl || !interactive) return; cli_txt_list_flush(&stations); if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0)) return; do { if (os_strcmp(addr, "") != 0) cli_txt_list_add(&stations, addr); os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0); } static void hostapd_cli_get_interfaces(struct wpa_ctrl *ctrl, struct dl_list *interfaces) { struct dirent *dent; DIR *dir; if (!ctrl || !interfaces) return; dir = opendir(ctrl_iface_dir); if (dir == NULL) return; while ((dent = readdir(dir))) { if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; cli_txt_list_add(interfaces, dent->d_name); } closedir(dir); } static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl) { struct dirent *dent; DIR *dir; dir = opendir(ctrl_iface_dir); if (dir == NULL) { printf("Control interface directory '%s' could not be " "opened.\n", ctrl_iface_dir); return; } printf("Available interfaces:\n"); while ((dent = readdir(dir))) { if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue; printf("%s\n", dent->d_name); } closedir(dir); } static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) { if (argc < 1) { hostapd_cli_list_interfaces(ctrl); return 0; } if (hostapd_cli_reconnect(argv[0]) != 0) { printf("Could not connect to interface '%s' - re-trying\n", ctrl_ifname); } return 0; } static char ** hostapd_complete_interface(const char *str, int pos) { int arg = get_cmd_arg_num(str, pos); char **res = NULL; DEFINE_DL_LIST(interfaces); switch (arg) { case 1: hostapd_cli_get_interfaces(ctrl_conn, &interfaces); res = cli_txt_list_array(&interfaces); cli_txt_list_flush(&interfaces); break; } return res; } static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[2048]; int res; if (argc != 2) { printf("Invalid SET command: needs two arguments (variable " "name and value)\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long SET command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static char ** hostapd_complete_set(const char *str, int pos) { int arg = get_cmd_arg_num(str, pos); const char *fields[] = { #ifdef CONFIG_WPS_TESTING "wps_version_number", "wps_testing_stub_cred", "wps_corrupt_pkhash", #endif /* CONFIG_WPS_TESTING */ #ifdef CONFIG_INTERWORKING "gas_frag_limit", #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_TESTING_OPTIONS "ext_mgmt_frame_handling", "ext_eapol_frame_io", #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_MBO "mbo_assoc_disallow", #endif /* CONFIG_MBO */ "deny_mac_file", "accept_mac_file", }; int i, num_fields = ARRAY_SIZE(fields); if (arg == 1) { char **res; res = os_calloc(num_fields + 1, sizeof(char *)); if (!res) return NULL; for (i = 0; i < num_fields; i++) { res[i] = os_strdup(fields[i]); if (!res[i]) return res; } return res; } return NULL; } static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; if (argc != 1) { printf("Invalid GET command: needs one argument (variable " "name)\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long GET command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static char ** hostapd_complete_get(const char *str, int pos) { int arg = get_cmd_arg_num(str, pos); const char *fields[] = { "version", "tls_library", }; int i, num_fields = ARRAY_SIZE(fields); if (arg == 1) { char **res; res = os_calloc(num_fields + 1, sizeof(char *)); if (!res) return NULL; for (i = 0; i < num_fields; i++) { res[i] = os_strdup(fields[i]); if (!res[i]) return res; } return res; } return NULL; } #ifdef CONFIG_FST static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; int i; int total; if (argc <= 0) { printf("FST command: parameters are required.\n"); return -1; } total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER"); for (i = 0; i < argc; i++) { res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s", argv[i]); if (os_snprintf_error(sizeof(cmd) - total, res)) { printf("Too long fst command.\n"); return -1; } total += res; } return wpa_ctrl_command(ctrl, cmd); } #endif /* CONFIG_FST */ static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; int i; char *tmp; int total; if (argc < 2) { printf("Invalid chan_switch command: needs at least two " "arguments (count and freq)\n" "usage: [sec_channel_offset=] " "[center_freq1=] [center_freq2=] [bandwidth=] " "[blocktx] [ht|vht]\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s", argv[0], argv[1]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long CHAN_SWITCH command.\n"); return -1; } total = res; for (i = 2; i < argc; i++) { tmp = cmd + total; res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]); if (os_snprintf_error(sizeof(cmd) - total, res)) { printf("Too long CHAN_SWITCH command.\n"); return -1; } total += res; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "ENABLE"); } static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "RELOAD"); } static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DISABLE"); } static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "UPDATE_BEACON"); } static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; if (argc < 2 || argc > 4) { printf("Invalid vendor command\n" "usage: [] [nested=<0|1>]\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0], argv[1], argc >= 3 ? argv[2] : "", argc == 4 ? " " : "", argc == 4 ? argv[3] : ""); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long VENDOR command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "ERP_FLUSH"); } static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s", argc >= 1 ? " " : "", argc >= 1 ? argv[0] : "", argc == 2 ? " " : "", argc == 2 ? argv[1] : ""); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long option\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[]) { if (argc == 0) return -1; return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]); } static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "PMKSA"); } static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "PMKSA_FLUSH"); } static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[2048]; int res; if (argc < 3 || argc > 6) { printf("Invalid set_neighbor command: needs 3-6 arguments\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s %s", argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "", argc >= 5 ? argv[4] : "", argc == 6 ? argv[5] : ""); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long SET_NEIGHBOR command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR"); } static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "REMOVE_NEIGHBOR", 1, argc, argv); } static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char cmd[256]; int res; if (argc != 1) { printf("Invalid req_lci command - requires destination address\n"); return -1; } res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long REQ_LCI command.\n"); return -1; } return wpa_ctrl_command(ctrl, cmd); } static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc, char *argv[]) { if (argc < 4) { printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n"); return -1; } return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv); } static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); } #ifdef CONFIG_DPP static int hostapd_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv); } static int hostapd_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv); } static int hostapd_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv); } static int hostapd_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv); } static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv); } static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); } static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv); } static int hostapd_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv); } static int hostapd_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN"); } static int hostapd_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv); } static int hostapd_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv); } static int hostapd_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv); } static int hostapd_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv); } static int hostapd_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv); } static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); } #ifdef CONFIG_DPP2 static int hostapd_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); } static int hostapd_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); } static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); } static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); } #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ static int hostapd_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv); } static int hostapd_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv); } static int hostapd_cli_cmd_poll_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "POLL_STA", 1, argc, argv); } static int hostapd_cli_cmd_req_beacon(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "REQ_BEACON", 2, argc, argv); } static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return wpa_ctrl_command(ctrl, "RELOAD_WPA_PSK"); } #ifdef ANDROID static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[]) { return hostapd_cli_cmd(ctrl, "DRIVER", 1, argc, argv); } #endif /* ANDROID */ struct hostapd_cli_cmd { const char *cmd; int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); char ** (*completion)(const char *str, int pos); const char *usage; }; static const struct hostapd_cli_cmd hostapd_cli_commands[] = { { "ping", hostapd_cli_cmd_ping, NULL, "= pings hostapd" }, { "mib", hostapd_cli_cmd_mib, NULL, "= get MIB variables (dot1x, dot11, radius)" }, { "relog", hostapd_cli_cmd_relog, NULL, "= reload/truncate debug log output file" }, { "status", hostapd_cli_cmd_status, NULL, "= show interface status info" }, { "sta", hostapd_cli_cmd_sta, hostapd_complete_stations, " = get MIB variables for one station" }, { "all_sta", hostapd_cli_cmd_all_sta, NULL, "= get MIB variables for all stations" }, { "list_sta", hostapd_cli_cmd_list_sta, NULL, "= list all stations" }, { "new_sta", hostapd_cli_cmd_new_sta, NULL, " = add a new station" }, { "deauthenticate", hostapd_cli_cmd_deauthenticate, hostapd_complete_stations, " = deauthenticate a station" }, { "disassociate", hostapd_cli_cmd_disassociate, hostapd_complete_stations, " = disassociate a station" }, #ifdef CONFIG_TAXONOMY { "signature", hostapd_cli_cmd_signature, hostapd_complete_stations, " = get taxonomy signature for a station" }, #endif /* CONFIG_TAXONOMY */ { "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations, " = send SA Query to a station" }, #ifdef CONFIG_WPS { "wps_pin", hostapd_cli_cmd_wps_pin, NULL, " [timeout] [addr] = add WPS Enrollee PIN" }, { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL, " = verify PIN checksum" }, { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL, "= indicate button pushed to initiate PBC" }, { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL, "= cancel the pending WPS operation" }, #ifdef CONFIG_WPS_NFC { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL, " = report read NFC tag with WPS data" }, { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL, " = build NFC configuration token" }, { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL, " = manager NFC password token" }, { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL, NULL }, #endif /* CONFIG_WPS_NFC */ { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL, " [params..] = enable/disable AP PIN" }, { "wps_config", hostapd_cli_cmd_wps_config, NULL, " = configure AP" }, { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL, "= show current WPS status" }, #endif /* CONFIG_WPS */ { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, "= send Disassociation Imminent notification" }, { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, "= send ESS Dissassociation Imminent notification" }, { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, "= send BSS Transition Management Request" }, { "get_config", hostapd_cli_cmd_get_config, NULL, "= show current configuration" }, { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help, "= show this usage help" }, { "interface", hostapd_cli_cmd_interface, hostapd_complete_interface, "[ifname] = show interfaces/select interface" }, #ifdef CONFIG_FST { "fst", hostapd_cli_cmd_fst, NULL, " = send FST-MANAGER control interface command" }, #endif /* CONFIG_FST */ { "raw", hostapd_cli_cmd_raw, NULL, " = send unprocessed command" }, { "level", hostapd_cli_cmd_level, NULL, " = change debug level" }, { "license", hostapd_cli_cmd_license, NULL, "= show full hostapd_cli license" }, { "quit", hostapd_cli_cmd_quit, NULL, "= exit hostapd_cli" }, { "set", hostapd_cli_cmd_set, hostapd_complete_set, " = set runtime variables" }, { "get", hostapd_cli_cmd_get, hostapd_complete_get, " = get runtime info" }, { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, " = set QoS Map set element" }, { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, hostapd_complete_stations, " = send QoS Map Configure frame" }, { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, " [sec_channel_offset=] [center_freq1=]\n" " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n" " = initiate channel switch announcement" }, { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, " \n" " = send WNM-Notification Subscription Remediation Request" }, { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, " [url]\n" " = send WNM-Notification imminent deauthentication indication" }, { "vendor", hostapd_cli_cmd_vendor, NULL, " []\n" " = send vendor driver command" }, { "enable", hostapd_cli_cmd_enable, NULL, "= enable hostapd on current interface" }, { "reload", hostapd_cli_cmd_reload, NULL, "= reload configuration for current interface" }, { "disable", hostapd_cli_cmd_disable, NULL, "= disable hostapd on current interface" }, { "update_beacon", hostapd_cli_cmd_update_beacon, NULL, "= update Beacon frame contents\n"}, { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, "= drop all ERP keys"}, { "log_level", hostapd_cli_cmd_log_level, NULL, "[level] = show/change log verbosity level" }, { "pmksa", hostapd_cli_cmd_pmksa, NULL, " = show PMKSA cache entries" }, { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, " = flush PMKSA cache" }, { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, " [lci=] [civic=] [stat]\n" " = add AP to neighbor database" }, { "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL, " = show neighbor database entries" }, { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, " [ssid=] = remove AP from neighbor database" }, { "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations, " = send LCI request to a station"}, { "req_range", hostapd_cli_cmd_req_range, NULL, " = send FTM range request"}, { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, " = show supported driver flags"}, #ifdef CONFIG_DPP { "dpp_qr_code", hostapd_cli_cmd_dpp_qr_code, NULL, "report a scanned DPP URI from a QR Code" }, { "dpp_bootstrap_gen", hostapd_cli_cmd_dpp_bootstrap_gen, NULL, "type= [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" }, { "dpp_bootstrap_remove", hostapd_cli_cmd_dpp_bootstrap_remove, NULL, "*| = remove DPP bootstrap information" }, { "dpp_bootstrap_get_uri", hostapd_cli_cmd_dpp_bootstrap_get_uri, NULL, " = get DPP bootstrap URI" }, { "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL, " = show DPP bootstrap information" }, { "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL, " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, { "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL, "peer= [own=] = initiate DPP bootstrapping" }, { "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL, " = start DPP listen" }, { "dpp_stop_listen", hostapd_cli_cmd_dpp_stop_listen, NULL, "= stop DPP listen" }, { "dpp_configurator_add", hostapd_cli_cmd_dpp_configurator_add, NULL, "[curve=..] [key=..] = add DPP configurator" }, { "dpp_configurator_remove", hostapd_cli_cmd_dpp_configurator_remove, NULL, "*| = remove DPP configurator" }, { "dpp_configurator_get_key", hostapd_cli_cmd_dpp_configurator_get_key, NULL, " = Get DPP configurator's private key" }, { "dpp_configurator_sign", hostapd_cli_cmd_dpp_configurator_sign, NULL, "conf= configurator= = generate self DPP configuration" }, { "dpp_pkex_add", hostapd_cli_cmd_dpp_pkex_add, NULL, "add PKEX code" }, { "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL, "*| = remove DPP pkex information" }, #ifdef CONFIG_DPP2 { "dpp_controller_start", hostapd_cli_cmd_dpp_controller_start, NULL, "[tcp_port=] [role=..] = start DPP controller" }, { "dpp_controller_stop", hostapd_cli_cmd_dpp_controller_stop, NULL, "= stop DPP controller" }, { "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL, "own= iter= = start DPP chirp" }, { "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL, "= stop DPP chirp" }, #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ { "accept_acl", hostapd_cli_cmd_accept_macacl, NULL, "=Add/Delete/Show/Clear accept MAC ACL" }, { "deny_acl", hostapd_cli_cmd_deny_macacl, NULL, "=Add/Delete/Show/Clear deny MAC ACL" }, { "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations, " = poll a STA to check connectivity with a QoS null frame" }, { "req_beacon", hostapd_cli_cmd_req_beacon, NULL, " [req_mode=] = send a Beacon report request to a station" }, { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL, "= reload wpa_psk_file only" }, #ifdef ANDROID { "driver", hostapd_cli_cmd_driver, NULL, " [] = send driver command data" }, #endif /* ANDROID */ { NULL, NULL, NULL, NULL } }; /* * Prints command usage, lines are padded with the specified string. */ static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd, const char *pad) { char c; size_t n; if (cmd->usage == NULL) return; fprintf(stream, "%s%s ", pad, cmd->cmd); for (n = 0; (c = cmd->usage[n]); n++) { fprintf(stream, "%c", c); if (c == '\n') fprintf(stream, "%s", pad); } fprintf(stream, "\n"); } static void print_help(FILE *stream, const char *cmd) { int n; fprintf(stream, "commands:\n"); for (n = 0; hostapd_cli_commands[n].cmd; n++) { if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd)) print_cmd_help(stream, &hostapd_cli_commands[n], " "); } } static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) { const struct hostapd_cli_cmd *cmd, *match = NULL; int count; count = 0; cmd = hostapd_cli_commands; while (cmd->cmd) { if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) { match = cmd; if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { /* we have an exact match */ count = 1; break; } count++; } cmd++; } if (count > 1) { printf("Ambiguous command '%s'; possible commands:", argv[0]); cmd = hostapd_cli_commands; while (cmd->cmd) { if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) { printf(" %s", cmd->cmd); } cmd++; } printf("\n"); } else if (count == 0) { printf("Unknown command '%s'\n", argv[0]); } else { match->handler(ctrl, argc - 1, &argv[1]); } } static void cli_event(const char *str) { const char *start, *s; start = os_strchr(str, '>'); if (start == NULL) return; start++; if (str_starts(start, AP_STA_CONNECTED)) { s = os_strchr(start, ' '); if (s == NULL) return; cli_txt_list_add(&stations, s + 1); return; } if (str_starts(start, AP_STA_DISCONNECTED)) { s = os_strchr(start, ' '); if (s == NULL) return; cli_txt_list_del_addr(&stations, s + 1); return; } } static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, int action_monitor) { int first = 1; if (ctrl_conn == NULL) return; while (wpa_ctrl_pending(ctrl)) { char buf[4096]; size_t len = sizeof(buf) - 1; if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { buf[len] = '\0'; if (action_monitor) hostapd_cli_action_process(buf, len); else { cli_event(buf); if (in_read && first) printf("\n"); first = 0; printf("%s\n", buf); } } else { printf("Could not read pending message.\n"); break; } } } static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx) { hostapd_cli_recv_pending(ctrl_conn, 0, 0); } static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx) { if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { printf("Connection to hostapd lost - trying to reconnect\n"); hostapd_cli_close_connection(); } if (!ctrl_conn && hostapd_cli_reconnect(ctrl_ifname) == 0) printf("Connection to hostapd re-established\n"); if (ctrl_conn) hostapd_cli_recv_pending(ctrl_conn, 1, 0); eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL); } static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx) { eloop_terminate(); } static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd) { char *argv[max_args]; int argc; argc = tokenize_cmd(cmd, argv); if (argc) wpa_request(ctrl_conn, argc, argv); } static void hostapd_cli_edit_eof_cb(void *ctx) { eloop_terminate(); } static char ** list_cmd_list(void) { char **res; int i, count; count = ARRAY_SIZE(hostapd_cli_commands); res = os_calloc(count + 1, sizeof(char *)); if (res == NULL) return NULL; for (i = 0; hostapd_cli_commands[i].cmd; i++) { res[i] = os_strdup(hostapd_cli_commands[i].cmd); if (res[i] == NULL) break; } return res; } static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str, int pos) { int i; for (i = 0; hostapd_cli_commands[i].cmd; i++) { if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0) continue; if (hostapd_cli_commands[i].completion) return hostapd_cli_commands[i].completion(str, pos); if (!hostapd_cli_commands[i].usage) return NULL; edit_clear_line(); printf("\r%s\n", hostapd_cli_commands[i].usage); edit_redraw(); break; } return NULL; } static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str, int pos) { char **res; const char *end; char *cmd; end = os_strchr(str, ' '); if (end == NULL || str + pos < end) return list_cmd_list(); cmd = os_malloc(pos + 1); if (cmd == NULL) return NULL; os_memcpy(cmd, str, pos); cmd[end - str] = '\0'; res = hostapd_cli_cmd_completion(cmd, str, pos); os_free(cmd); return res; } static void hostapd_cli_interactive(void) { char *hfile = NULL; char *home; printf("\nInteractive mode\n\n"); #ifdef CONFIG_HOSTAPD_CLI_HISTORY_DIR home = CONFIG_HOSTAPD_CLI_HISTORY_DIR; #else /* CONFIG_HOSTAPD_CLI_HISTORY_DIR */ home = getenv("HOME"); #endif /* CONFIG_HOSTAPD_CLI_HISTORY_DIR */ if (home) { const char *fname = ".hostapd_cli_history"; int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; hfile = os_malloc(hfile_len); if (hfile) os_snprintf(hfile, hfile_len, "%s/%s", home, fname); } eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL); edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb, hostapd_cli_edit_completion_cb, NULL, hfile, NULL); eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL); eloop_run(); cli_txt_list_flush(&stations); edit_deinit(hfile, NULL); os_free(hfile); eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL); } static void hostapd_cli_cleanup(void) { hostapd_cli_close_connection(); if (pid_file) os_daemonize_terminate(pid_file); os_program_deinit(); } static void hostapd_cli_action(struct wpa_ctrl *ctrl) { fd_set rfds; int fd, res; struct timeval tv; char buf[256]; size_t len; fd = wpa_ctrl_get_fd(ctrl); while (!hostapd_cli_quit) { FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = ping_interval; tv.tv_usec = 0; res = select(fd + 1, &rfds, NULL, NULL, &tv); if (res < 0 && errno != EINTR) { perror("select"); break; } if (FD_ISSET(fd, &rfds)) hostapd_cli_recv_pending(ctrl, 0, 1); else { len = sizeof(buf) - 1; if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, hostapd_cli_action_process) < 0 || len < 4 || os_memcmp(buf, "PONG", 4) != 0) { printf("hostapd did not reply to PING " "command - exiting\n"); break; } } } } int main(int argc, char *argv[]) { int warning_displayed = 0; int c; int daemonize = 0; int reconnect = 0; if (os_program_init()) return -1; for (;;) { c = getopt(argc, argv, "a:BhG:i:p:P:rs:v"); if (c < 0) break; switch (c) { case 'a': action_file = optarg; break; case 'B': daemonize = 1; break; case 'G': ping_interval = atoi(optarg); break; case 'h': usage(); return 0; case 'v': printf("%s\n", hostapd_cli_version); return 0; case 'i': os_free(ctrl_ifname); ctrl_ifname = os_strdup(optarg); break; case 'p': ctrl_iface_dir = optarg; break; case 'P': pid_file = optarg; break; case 'r': reconnect = 1; break; case 's': client_socket_dir = optarg; break; default: usage(); return -1; } } interactive = (argc == optind) && (action_file == NULL); if (interactive) { printf("%s\n\n%s\n\n", hostapd_cli_version, cli_license); } if (eloop_init()) return -1; for (;;) { if (ctrl_ifname == NULL) { struct dirent *dent; DIR *dir = opendir(ctrl_iface_dir); if (dir) { while ((dent = readdir(dir))) { if (os_strcmp(dent->d_name, ".") == 0 || os_strcmp(dent->d_name, "..") == 0) continue; printf("Selected interface '%s'\n", dent->d_name); ctrl_ifname = os_strdup(dent->d_name); break; } closedir(dir); } } hostapd_cli_reconnect(ctrl_ifname); if (ctrl_conn) { if (warning_displayed) printf("Connection established.\n"); break; } if (!interactive && !reconnect) { perror("Failed to connect to hostapd - " "wpa_ctrl_open"); return -1; } if (!warning_displayed) { printf("Could not connect to hostapd - re-trying\n"); warning_displayed = 1; } os_sleep(1, 0); continue; } if (action_file && !hostapd_cli_attached) return -1; if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue()) return -1; if (reconnect && action_file && ctrl_ifname) { while (!hostapd_cli_quit) { if (ctrl_conn) hostapd_cli_action(ctrl_conn); os_sleep(1, 0); hostapd_cli_reconnect(ctrl_ifname); } } else if (interactive) hostapd_cli_interactive(); else if (action_file) hostapd_cli_action(ctrl_conn); else wpa_request(ctrl_conn, argc - optind, &argv[optind]); unregister_event_handler(ctrl_conn); os_free(ctrl_ifname); eloop_destroy(); hostapd_cli_cleanup(); return 0; } #else /* CONFIG_NO_CTRL_IFACE */ int main(int argc, char *argv[]) { return -1; } #endif /* CONFIG_NO_CTRL_IFACE */ diff --git a/contrib/wpa/hostapd/main.c b/contrib/wpa/hostapd/main.c index 4f2d1f21659e..c9ec38d19f88 100644 --- a/contrib/wpa/hostapd/main.c +++ b/contrib/wpa/hostapd/main.c @@ -1,940 +1,940 @@ /* * hostapd / main() - * Copyright (c) 2002-2019, Jouni Malinen + * Copyright (c) 2002-2022, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS #include #include #endif /* CONFIG_NATIVE_WINDOWS */ #include "utils/common.h" #include "utils/eloop.h" #include "utils/uuid.h" #include "crypto/random.h" #include "crypto/tls.h" #include "common/version.h" #include "common/dpp.h" #include "drivers/driver.h" #include "eap_server/eap.h" #include "eap_server/tncs.h" #include "ap/hostapd.h" #include "ap/ap_config.h" #include "ap/ap_drv_ops.h" #include "ap/dpp_hostapd.h" #include "fst/fst.h" #include "config_file.h" #include "eap_register.h" #include "ctrl_iface.h" struct hapd_global { void **drv_priv; size_t drv_count; }; static struct hapd_global global; #ifndef CONFIG_NO_HOSTAPD_LOGGER static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, int level, const char *txt, size_t len) { struct hostapd_data *hapd = ctx; char *format, *module_str; int maxlen; int conf_syslog_level, conf_stdout_level; unsigned int conf_syslog, conf_stdout; maxlen = len + 100; format = os_malloc(maxlen); if (!format) return; if (hapd && hapd->conf) { conf_syslog_level = hapd->conf->logger_syslog_level; conf_stdout_level = hapd->conf->logger_stdout_level; conf_syslog = hapd->conf->logger_syslog; conf_stdout = hapd->conf->logger_stdout; } else { conf_syslog_level = conf_stdout_level = 0; conf_syslog = conf_stdout = (unsigned int) -1; } switch (module) { case HOSTAPD_MODULE_IEEE80211: module_str = "IEEE 802.11"; break; case HOSTAPD_MODULE_IEEE8021X: module_str = "IEEE 802.1X"; break; case HOSTAPD_MODULE_RADIUS: module_str = "RADIUS"; break; case HOSTAPD_MODULE_WPA: module_str = "WPA"; break; case HOSTAPD_MODULE_DRIVER: module_str = "DRIVER"; break; case HOSTAPD_MODULE_MLME: module_str = "MLME"; break; default: module_str = NULL; break; } if (hapd && hapd->conf && addr) os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", hapd->conf->iface, MAC2STR(addr), module_str ? " " : "", module_str ? module_str : "", txt); else if (hapd && hapd->conf) os_snprintf(format, maxlen, "%s:%s%s %s", hapd->conf->iface, module_str ? " " : "", module_str ? module_str : "", txt); else if (addr) os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", MAC2STR(addr), module_str ? " " : "", module_str ? module_str : "", txt); else os_snprintf(format, maxlen, "%s%s%s", module_str ? module_str : "", module_str ? ": " : "", txt); #ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) conf_stdout = 0; #endif /* CONFIG_DEBUG_SYSLOG */ if ((conf_stdout & module) && level >= conf_stdout_level) { wpa_debug_print_timestamp(); wpa_printf(MSG_INFO, "%s", format); } #ifndef CONFIG_NATIVE_WINDOWS if ((conf_syslog & module) && level >= conf_syslog_level) { int priority; switch (level) { case HOSTAPD_LEVEL_DEBUG_VERBOSE: case HOSTAPD_LEVEL_DEBUG: priority = LOG_DEBUG; break; case HOSTAPD_LEVEL_INFO: priority = LOG_INFO; break; case HOSTAPD_LEVEL_NOTICE: priority = LOG_NOTICE; break; case HOSTAPD_LEVEL_WARNING: priority = LOG_WARNING; break; default: priority = LOG_INFO; break; } syslog(priority, "%s", format); } #endif /* CONFIG_NATIVE_WINDOWS */ os_free(format); } #endif /* CONFIG_NO_HOSTAPD_LOGGER */ /** * hostapd_driver_init - Preparate driver interface */ static int hostapd_driver_init(struct hostapd_iface *iface) { struct wpa_init_params params; size_t i; struct hostapd_data *hapd = iface->bss[0]; struct hostapd_bss_config *conf = hapd->conf; u8 *b = conf->bssid; struct wpa_driver_capa capa; if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); return -1; } /* Initialize the driver interface */ if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) b = NULL; os_memset(¶ms, 0, sizeof(params)); for (i = 0; wpa_drivers[i]; i++) { if (wpa_drivers[i] != hapd->driver) continue; if (global.drv_priv[i] == NULL && wpa_drivers[i]->global_init) { global.drv_priv[i] = wpa_drivers[i]->global_init(iface->interfaces); if (global.drv_priv[i] == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize " "driver '%s'", wpa_drivers[i]->name); return -1; } } params.global_priv = global.drv_priv[i]; break; } params.bssid = b; params.ifname = hapd->conf->iface; params.driver_params = hapd->iconf->driver_params; params.use_pae_group_addr = hapd->conf->use_pae_group_addr; params.num_bridge = hapd->iface->num_bss; params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); if (params.bridge == NULL) return -1; for (i = 0; i < hapd->iface->num_bss; i++) { struct hostapd_data *bss = hapd->iface->bss[i]; if (bss->conf->bridge[0]) params.bridge[i] = bss->conf->bridge; } params.own_addr = hapd->own_addr; hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); os_free(params.bridge); if (hapd->drv_priv == NULL) { wpa_printf(MSG_ERROR, "%s driver initialization failed.", hapd->driver->name); hapd->driver = NULL; return -1; } if (hapd->driver->get_capa && hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { struct wowlan_triggers *triggs; iface->drv_flags = capa.flags; iface->drv_flags2 = capa.flags2; iface->probe_resp_offloads = capa.probe_resp_offloads; /* * Use default extended capa values from per-radio information */ iface->extended_capa = capa.extended_capa; iface->extended_capa_mask = capa.extended_capa_mask; iface->extended_capa_len = capa.extended_capa_len; iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; /* * Override extended capa with per-interface type (AP), if * available from the driver. */ hostapd_get_ext_capa(iface); triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); if (triggs && hapd->driver->set_wowlan) { if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) wpa_printf(MSG_ERROR, "set_wowlan failed"); } os_free(triggs); } return 0; } /** * hostapd_interface_init - Read configuration file and init BSS data * * This function is used to parse configuration file for a full interface (one * or more BSSes sharing the same radio) and allocate memory for the BSS * interfaces. No actual driver operations are started. */ static struct hostapd_iface * hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name, const char *config_fname, int debug) { struct hostapd_iface *iface; int k; wpa_printf(MSG_DEBUG, "Configuration file: %s", config_fname); iface = hostapd_init(interfaces, config_fname); if (!iface) return NULL; if (if_name) { os_strlcpy(iface->conf->bss[0]->iface, if_name, sizeof(iface->conf->bss[0]->iface)); } iface->interfaces = interfaces; for (k = 0; k < debug; k++) { if (iface->bss[0]->conf->logger_stdout_level > 0) iface->bss[0]->conf->logger_stdout_level--; } if (iface->conf->bss[0]->iface[0] == '\0' && !hostapd_drv_none(iface->bss[0])) { wpa_printf(MSG_ERROR, "Interface name not specified in %s, nor by '-i' parameter", config_fname); hostapd_interface_deinit_free(iface); return NULL; } return iface; } /** * handle_term - SIGINT and SIGTERM handler to terminate hostapd process */ static void handle_term(int sig, void *signal_ctx) { wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); eloop_terminate(); } #ifndef CONFIG_NATIVE_WINDOWS static int handle_reload_iface(struct hostapd_iface *iface, void *ctx) { if (hostapd_reload_config(iface) < 0) { wpa_printf(MSG_WARNING, "Failed to read new configuration " "file - continuing with old."); } return 0; } /** * handle_reload - SIGHUP handler to reload configuration */ static void handle_reload(int sig, void *signal_ctx) { struct hapd_interfaces *interfaces = signal_ctx; wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", sig); hostapd_for_each_interface(interfaces, handle_reload_iface, NULL); } static void handle_dump_state(int sig, void *signal_ctx) { /* Not used anymore - ignore signal */ } #endif /* CONFIG_NATIVE_WINDOWS */ static int hostapd_global_init(struct hapd_interfaces *interfaces, const char *entropy_file) { int i; os_memset(&global, 0, sizeof(global)); hostapd_logger_register_cb(hostapd_logger_cb); if (eap_server_register_methods()) { wpa_printf(MSG_ERROR, "Failed to register EAP methods"); return -1; } if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); return -1; } interfaces->eloop_initialized = 1; random_init(entropy_file); #ifndef CONFIG_NATIVE_WINDOWS eloop_register_signal(SIGHUP, handle_reload, interfaces); eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); #endif /* CONFIG_NATIVE_WINDOWS */ eloop_register_signal_terminate(handle_term, interfaces); #ifndef CONFIG_NATIVE_WINDOWS openlog("hostapd", 0, LOG_DAEMON); #endif /* CONFIG_NATIVE_WINDOWS */ for (i = 0; wpa_drivers[i]; i++) global.drv_count++; if (global.drv_count == 0) { wpa_printf(MSG_ERROR, "No drivers enabled"); return -1; } global.drv_priv = os_calloc(global.drv_count, sizeof(void *)); if (global.drv_priv == NULL) return -1; return 0; } static void hostapd_global_deinit(const char *pid_file, int eloop_initialized) { int i; for (i = 0; wpa_drivers[i] && global.drv_priv; i++) { if (!global.drv_priv[i]) continue; wpa_drivers[i]->global_deinit(global.drv_priv[i]); } os_free(global.drv_priv); global.drv_priv = NULL; #ifdef EAP_SERVER_TNC tncs_global_deinit(); #endif /* EAP_SERVER_TNC */ random_deinit(); if (eloop_initialized) eloop_destroy(); #ifndef CONFIG_NATIVE_WINDOWS closelog(); #endif /* CONFIG_NATIVE_WINDOWS */ eap_server_unregister_methods(); os_daemonize_terminate(pid_file); } static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, const char *pid_file) { #ifdef EAP_SERVER_TNC int tnc = 0; size_t i, k; for (i = 0; !tnc && i < ifaces->count; i++) { for (k = 0; k < ifaces->iface[i]->num_bss; k++) { if (ifaces->iface[i]->bss[0]->conf->tnc) { tnc++; break; } } } if (tnc && tncs_global_init() < 0) { wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); return -1; } #endif /* EAP_SERVER_TNC */ if (daemonize) { if (os_daemonize(pid_file)) { wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno)); return -1; } if (eloop_sock_requeue()) { wpa_printf(MSG_ERROR, "eloop_sock_requeue: %s", strerror(errno)); return -1; } } eloop_run(); return 0; } static void show_version(void) { fprintf(stderr, "hostapd v%s\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2019, Jouni Malinen " + "Copyright (c) 2002-2022, Jouni Malinen " "and contributors\n", VERSION_STR); } static void usage(void) { show_version(); fprintf(stderr, "\n" "usage: hostapd [-hdBKtv] [-P ] [-e ] " "\\\n" " [-g ] [-G ]\\\n" " [-i ]\\\n" " \n" "\n" "options:\n" " -h show this usage\n" " -d show more debug messages (-dd for even more)\n" " -B run daemon in the background\n" " -e entropy file\n" " -g global control interface path\n" " -G group for control interfaces\n" " -P PID file\n" " -K include key data in debug messages\n" #ifdef CONFIG_DEBUG_FILE " -f log output to debug file instead of stdout\n" #endif /* CONFIG_DEBUG_FILE */ #ifdef CONFIG_DEBUG_LINUX_TRACING " -T record to Linux tracing in addition to logging\n" " (records all messages regardless of debug verbosity)\n" #endif /* CONFIG_DEBUG_LINUX_TRACING */ " -i list of interface names to use\n" #ifdef CONFIG_DEBUG_SYSLOG " -s log output to syslog instead of stdout\n" #endif /* CONFIG_DEBUG_SYSLOG */ " -S start all the interfaces synchronously\n" " -t include timestamps in some debug messages\n" " -v show hostapd version\n"); exit(1); } static const char * hostapd_msg_ifname_cb(void *ctx) { struct hostapd_data *hapd = ctx; if (hapd && hapd->conf) return hapd->conf->iface; return NULL; } static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces, const char *path) { #ifndef CONFIG_CTRL_IFACE_UDP char *pos; #endif /* !CONFIG_CTRL_IFACE_UDP */ os_free(interfaces->global_iface_path); interfaces->global_iface_path = os_strdup(path); if (interfaces->global_iface_path == NULL) return -1; #ifndef CONFIG_CTRL_IFACE_UDP pos = os_strrchr(interfaces->global_iface_path, '/'); if (pos == NULL) { wpa_printf(MSG_ERROR, "No '/' in the global control interface " "file"); os_free(interfaces->global_iface_path); interfaces->global_iface_path = NULL; return -1; } *pos = '\0'; interfaces->global_iface_name = pos + 1; #endif /* !CONFIG_CTRL_IFACE_UDP */ return 0; } static int hostapd_get_ctrl_iface_group(struct hapd_interfaces *interfaces, const char *group) { #ifndef CONFIG_NATIVE_WINDOWS struct group *grp; grp = getgrnam(group); if (grp == NULL) { wpa_printf(MSG_ERROR, "Unknown group '%s'", group); return -1; } interfaces->ctrl_iface_group = grp->gr_gid; #endif /* CONFIG_NATIVE_WINDOWS */ return 0; } static int hostapd_get_interface_names(char ***if_names, size_t *if_names_size, char *arg) { char *if_name, *tmp, **nnames; size_t i; if (!arg) return -1; if_name = strtok_r(arg, ",", &tmp); while (if_name) { nnames = os_realloc_array(*if_names, 1 + *if_names_size, sizeof(char *)); if (!nnames) goto fail; *if_names = nnames; (*if_names)[*if_names_size] = os_strdup(if_name); if (!(*if_names)[*if_names_size]) goto fail; (*if_names_size)++; if_name = strtok_r(NULL, ",", &tmp); } return 0; fail: for (i = 0; i < *if_names_size; i++) os_free((*if_names)[i]); os_free(*if_names); *if_names = NULL; *if_names_size = 0; return -1; } #ifdef CONFIG_WPS static int gen_uuid(const char *txt_addr) { u8 addr[ETH_ALEN]; u8 uuid[UUID_LEN]; char buf[100]; if (hwaddr_aton(txt_addr, addr) < 0) return -1; uuid_gen_mac_addr(addr, uuid); if (uuid_bin2str(uuid, buf, sizeof(buf)) < 0) return -1; printf("%s\n", buf); return 0; } #endif /* CONFIG_WPS */ #ifndef HOSTAPD_CLEANUP_INTERVAL #define HOSTAPD_CLEANUP_INTERVAL 10 #endif /* HOSTAPD_CLEANUP_INTERVAL */ static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx) { hostapd_periodic_iface(iface); return 0; } /* Periodic cleanup tasks */ static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx) { struct hapd_interfaces *interfaces = eloop_ctx; eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, hostapd_periodic, interfaces, NULL); hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL); } int main(int argc, char *argv[]) { struct hapd_interfaces interfaces; int ret = 1; size_t i, j; int c, debug = 0, daemonize = 0; char *pid_file = NULL; const char *log_file = NULL; const char *entropy_file = NULL; char **bss_config = NULL, **tmp_bss; size_t num_bss_configs = 0; #ifdef CONFIG_DEBUG_LINUX_TRACING int enable_trace_dbg = 0; #endif /* CONFIG_DEBUG_LINUX_TRACING */ int start_ifaces_in_sync = 0; char **if_names = NULL; size_t if_names_size = 0; #ifdef CONFIG_DPP struct dpp_global_config dpp_conf; #endif /* CONFIG_DPP */ if (os_program_init()) return -1; os_memset(&interfaces, 0, sizeof(interfaces)); interfaces.reload_config = hostapd_reload_config; interfaces.config_read_cb = hostapd_config_read; interfaces.for_each_interface = hostapd_for_each_interface; interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; interfaces.driver_init = hostapd_driver_init; interfaces.global_iface_path = NULL; interfaces.global_iface_name = NULL; interfaces.global_ctrl_sock = -1; dl_list_init(&interfaces.global_ctrl_dst); #ifdef CONFIG_ETH_P_OUI dl_list_init(&interfaces.eth_p_oui); #endif /* CONFIG_ETH_P_OUI */ #ifdef CONFIG_DPP os_memset(&dpp_conf, 0, sizeof(dpp_conf)); dpp_conf.cb_ctx = &interfaces; #ifdef CONFIG_DPP2 dpp_conf.remove_bi = hostapd_dpp_remove_bi; #endif /* CONFIG_DPP2 */ interfaces.dpp = dpp_global_init(&dpp_conf); if (!interfaces.dpp) return -1; #endif /* CONFIG_DPP */ for (;;) { c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:"); if (c < 0) break; switch (c) { case 'h': usage(); break; case 'd': debug++; if (wpa_debug_level > 0) wpa_debug_level--; break; case 'B': daemonize++; break; case 'e': entropy_file = optarg; break; case 'f': log_file = optarg; break; case 'K': wpa_debug_show_keys++; break; case 'P': os_free(pid_file); pid_file = os_rel2abs_path(optarg); break; case 't': wpa_debug_timestamp++; break; #ifdef CONFIG_DEBUG_LINUX_TRACING case 'T': enable_trace_dbg = 1; break; #endif /* CONFIG_DEBUG_LINUX_TRACING */ case 'v': show_version(); exit(1); break; case 'g': if (hostapd_get_global_ctrl_iface(&interfaces, optarg)) return -1; break; case 'G': if (hostapd_get_ctrl_iface_group(&interfaces, optarg)) return -1; break; case 'b': tmp_bss = os_realloc_array(bss_config, num_bss_configs + 1, sizeof(char *)); if (tmp_bss == NULL) goto out; bss_config = tmp_bss; bss_config[num_bss_configs++] = optarg; break; #ifdef CONFIG_DEBUG_SYSLOG case 's': wpa_debug_syslog = 1; break; #endif /* CONFIG_DEBUG_SYSLOG */ case 'S': start_ifaces_in_sync = 1; break; #ifdef CONFIG_WPS case 'u': return gen_uuid(optarg); #endif /* CONFIG_WPS */ case 'i': if (hostapd_get_interface_names(&if_names, &if_names_size, optarg)) goto out; break; default: usage(); break; } } if (optind == argc && interfaces.global_iface_path == NULL && num_bss_configs == 0) usage(); wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); if (log_file) wpa_debug_open_file(log_file); if (!log_file && !wpa_debug_syslog) wpa_debug_setup_stdout(); #ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) wpa_debug_open_syslog(); #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef CONFIG_DEBUG_LINUX_TRACING if (enable_trace_dbg) { int tret = wpa_debug_open_linux_tracing(); if (tret) { wpa_printf(MSG_ERROR, "Failed to enable trace logging"); return -1; } } #endif /* CONFIG_DEBUG_LINUX_TRACING */ interfaces.count = argc - optind; if (interfaces.count || num_bss_configs) { interfaces.iface = os_calloc(interfaces.count + num_bss_configs, sizeof(struct hostapd_iface *)); if (interfaces.iface == NULL) { wpa_printf(MSG_ERROR, "malloc failed"); return -1; } } if (hostapd_global_init(&interfaces, entropy_file)) { wpa_printf(MSG_ERROR, "Failed to initialize global context"); return -1; } eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, hostapd_periodic, &interfaces, NULL); if (fst_global_init()) { wpa_printf(MSG_ERROR, "Failed to initialize global FST context"); goto out; } #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE) if (!fst_global_add_ctrl(fst_ctrl_cli)) wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl"); #endif /* CONFIG_FST && CONFIG_CTRL_IFACE */ /* Allocate and parse configuration for full interface files */ for (i = 0; i < interfaces.count; i++) { char *if_name = NULL; if (i < if_names_size) if_name = if_names[i]; interfaces.iface[i] = hostapd_interface_init(&interfaces, if_name, argv[optind + i], debug); if (!interfaces.iface[i]) { wpa_printf(MSG_ERROR, "Failed to initialize interface"); goto out; } if (start_ifaces_in_sync) interfaces.iface[i]->need_to_start_in_sync = 1; } /* Allocate and parse configuration for per-BSS files */ for (i = 0; i < num_bss_configs; i++) { struct hostapd_iface *iface; char *fname; wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]); fname = os_strchr(bss_config[i], ':'); if (fname == NULL) { wpa_printf(MSG_ERROR, "Invalid BSS config identifier '%s'", bss_config[i]); goto out; } *fname++ = '\0'; iface = hostapd_interface_init_bss(&interfaces, bss_config[i], fname, debug); if (iface == NULL) goto out; for (j = 0; j < interfaces.count; j++) { if (interfaces.iface[j] == iface) break; } if (j == interfaces.count) { struct hostapd_iface **tmp; tmp = os_realloc_array(interfaces.iface, interfaces.count + 1, sizeof(struct hostapd_iface *)); if (tmp == NULL) { hostapd_interface_deinit_free(iface); goto out; } interfaces.iface = tmp; interfaces.iface[interfaces.count++] = iface; } } /* * Enable configured interfaces. Depending on channel configuration, * this may complete full initialization before returning or use a * callback mechanism to complete setup in case of operations like HT * co-ex scans, ACS, or DFS are needed to determine channel parameters. * In such case, the interface will be enabled from eloop context within * hostapd_global_run(). */ interfaces.terminate_on_error = interfaces.count; for (i = 0; i < interfaces.count; i++) { if (hostapd_driver_init(interfaces.iface[i]) || hostapd_setup_interface(interfaces.iface[i])) goto out; } hostapd_global_ctrl_iface_init(&interfaces); if (hostapd_global_run(&interfaces, daemonize, pid_file)) { wpa_printf(MSG_ERROR, "Failed to start eloop"); goto out; } ret = 0; out: hostapd_global_ctrl_iface_deinit(&interfaces); /* Deinitialize all interfaces */ for (i = 0; i < interfaces.count; i++) { if (!interfaces.iface[i]) continue; interfaces.iface[i]->driver_ap_teardown = !!(interfaces.iface[i]->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); hostapd_interface_deinit_free(interfaces.iface[i]); interfaces.iface[i] = NULL; } os_free(interfaces.iface); interfaces.iface = NULL; interfaces.count = 0; #ifdef CONFIG_DPP dpp_global_deinit(interfaces.dpp); #endif /* CONFIG_DPP */ if (interfaces.eloop_initialized) eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL); hostapd_global_deinit(pid_file, interfaces.eloop_initialized); os_free(pid_file); wpa_debug_close_syslog(); if (log_file) wpa_debug_close_file(); wpa_debug_close_linux_tracing(); os_free(bss_config); for (i = 0; i < if_names_size; i++) os_free(if_names[i]); os_free(if_names); fst_global_deinit(); os_program_deinit(); return ret; } diff --git a/contrib/wpa/hs20/server/Makefile b/contrib/wpa/hs20/server/Makefile deleted file mode 100644 index 0cab6d6b010a..000000000000 --- a/contrib/wpa/hs20/server/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -ALL=hs20_spp_server - -include ../../src/build.rules - -CFLAGS += -I../../src -CFLAGS += -I../../src/utils -CFLAGS += -I../../src/crypto - -LIBS += -lsqlite3 - -# Using glibc < 2.17 requires -lrt for clock_gettime() -LIBS += -lrt - -ifndef CONFIG_NO_GITVER -# Add VERSION_STR postfix for builds from a git repository -ifeq ($(wildcard ../../.git),../../.git) -GITVER := $(shell git describe --dirty=+) -ifneq ($(GITVER),) -CFLAGS += -DGIT_VERSION_STR_POSTFIX=\"-$(GITVER)\" -endif -endif -endif - -OBJS=spp_server.o -OBJS += hs20_spp_server.o -OBJS += ../../src/utils/xml-utils.o -OBJS += ../../src/utils/base64.o -OBJS += ../../src/utils/common.o -OBJS += ../../src/utils/os_unix.o -OBJS += ../../src/utils/wpa_debug.o -OBJS += ../../src/crypto/md5-internal.o -CFLAGS += $(shell xml2-config --cflags) -LIBS += $(shell xml2-config --libs) -OBJS += ../../src/utils/xml_libxml2.o - -_OBJS_VAR := OBJS -include ../../src/objs.mk -hs20_spp_server: $(OBJS) - $(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS) - -clean: common-clean - rm -f core *~ diff --git a/contrib/wpa/hs20/server/ca/clean.sh b/contrib/wpa/hs20/server/ca/clean.sh deleted file mode 100755 index c72dcbda45e9..000000000000 --- a/contrib/wpa/hs20/server/ca/clean.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -for i in server-client server server-revoked user ocsp; do - rm -f $i.csr $i.key $i.pem -done - -rm -f openssl.cnf.tmp -if [ -d demoCA ]; then - rm -r demoCA -fi -rm -f ca.pem logo.asn1 logo.der server.der ocsp-server-cache.der -rm -f my-openssl.cnf my-openssl-root.cnf -#rm -r rootCA diff --git a/contrib/wpa/hs20/server/ca/est-csrattrs.cnf b/contrib/wpa/hs20/server/ca/est-csrattrs.cnf deleted file mode 100644 index b50ea00d0b77..000000000000 --- a/contrib/wpa/hs20/server/ca/est-csrattrs.cnf +++ /dev/null @@ -1,17 +0,0 @@ -asn1 = SEQUENCE:attrs - -[attrs] -#oid1 = OID:challengePassword -attr1 = SEQUENCE:extreq -oid2 = OID:sha256WithRSAEncryption - -[extreq] -oid = OID:extensionRequest -vals = SET:extreqvals - -[extreqvals] - -oid1 = OID:macAddress -#oid2 = OID:imei -#oid3 = OID:meid -#oid4 = OID:DevId diff --git a/contrib/wpa/hs20/server/ca/est-csrattrs.sh b/contrib/wpa/hs20/server/ca/est-csrattrs.sh deleted file mode 100755 index 0b73a0408284..000000000000 --- a/contrib/wpa/hs20/server/ca/est-csrattrs.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -openssl asn1parse -genconf est-csrattrs.cnf -out est-csrattrs.der -oid hs20.oid -base64 est-csrattrs.der > est-attrs.b64 diff --git a/contrib/wpa/hs20/server/ca/hs20.oid b/contrib/wpa/hs20/server/ca/hs20.oid deleted file mode 100644 index a829ff29bf44..000000000000 --- a/contrib/wpa/hs20/server/ca/hs20.oid +++ /dev/null @@ -1,7 +0,0 @@ -1.3.6.1.1.1.1.22 macAddress -1.2.840.113549.1.9.14 extensionRequest -1.3.6.1.4.1.40808.1.1.1 id-wfa-hotspot-friendlyName -1.3.6.1.4.1.40808.1.1.2 id-kp-HS2.0Auth -1.3.6.1.4.1.40808.1.1.3 imei -1.3.6.1.4.1.40808.1.1.4 meid -1.3.6.1.4.1.40808.1.1.5 DevId diff --git a/contrib/wpa/hs20/server/ca/ocsp-req.sh b/contrib/wpa/hs20/server/ca/ocsp-req.sh deleted file mode 100755 index 931a20696d02..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-req.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -for i in *.pem; do - echo "===[ $i ]===================" - openssl ocsp -text -CAfile ca.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ - -# openssl ocsp -text -CAfile rootCA/cacert.pem -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ - -# openssl ocsp -text -CAfile rootCA/cacert.pem -verify_other demoCA/cacert.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ -# openssl ocsp -text -CAfile rootCA/cacert.pem -VAfile ca.pem -trust_other -issuer demoCA/cacert.pem -cert $i -url http://localhost:8888/ -done diff --git a/contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh b/contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh deleted file mode 100755 index 116c6e1c3d01..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-responder-ica.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner demoCA/cacert.pem -rkey demoCA/private/cakey-plain.pem -CA demoCA/cacert.pem -resp_no_certs -text diff --git a/contrib/wpa/hs20/server/ca/ocsp-responder.sh b/contrib/wpa/hs20/server/ca/ocsp-responder.sh deleted file mode 100755 index 620947d01af0..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-responder.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err diff --git a/contrib/wpa/hs20/server/ca/ocsp-update-cache.sh b/contrib/wpa/hs20/server/ca/ocsp-update-cache.sh deleted file mode 100755 index f2b23250cadd..000000000000 --- a/contrib/wpa/hs20/server/ca/ocsp-update-cache.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# NOTE: You may need to replace 'localhost' with your OCSP server hostname. -openssl ocsp \ - -no_nonce \ - -CAfile ca.pem \ - -verify_other demoCA/cacert.pem \ - -issuer demoCA/cacert.pem \ - -cert server.pem \ - -url http://localhost:8888/ \ - -respout ocsp-server-cache.der diff --git a/contrib/wpa/hs20/server/ca/openssl-root.cnf b/contrib/wpa/hs20/server/ca/openssl-root.cnf deleted file mode 100644 index 5bc50be1dbc9..000000000000 --- a/contrib/wpa/hs20/server/ca/openssl-root.cnf +++ /dev/null @@ -1,125 +0,0 @@ -# OpenSSL configuration file for Hotspot 2.0 PKI (Root CA) - -HOME = . -RANDFILE = $ENV::HOME/.rnd -oid_section = new_oids - -[ new_oids ] - -#logotypeoid=1.3.6.1.5.5.7.1.12 - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -#################################################################### -[ CA_default ] - -dir = ./rootCA # Where everything is kept -certs = $dir/certs # Where the issued certs are kept -crl_dir = $dir/crl # Where the issued crl are kept -database = $dir/index.txt # database index file. -#unique_subject = no # Set to 'no' to allow creation of - # several certificates with same subject -new_certs_dir = $dir/newcerts # default place for new certs. - -certificate = $dir/cacert.pem # The CA certificate -serial = $dir/serial # The current serial number -crlnumber = $dir/crlnumber # the current crl number - # must be commented out to leave a V1 CRL -crl = $dir/crl.pem # The current CRL -private_key = $dir/private/cakey.pem# The private key -RANDFILE = $dir/private/.rand # private random number file - -x509_extensions = usr_cert # The extentions to add to the cert - -name_opt = ca_default # Subject Name options -cert_opt = ca_default # Certificate field options - -default_days = 365 # how long to certify for -default_crl_days= 30 # how long before next CRL -default_md = default # use public key default MD -preserve = no # keep passed DN ordering - -policy = policy_match - -# For the CA policy -[ policy_match ] -countryName = match -stateOrProvinceName = optional -organizationName = match -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ policy_anything ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ req ] -default_bits = 2048 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -attributes = req_attributes -x509_extensions = v3_ca # The extentions to add to the self signed cert - -input_password = @PASSWORD@ -output_password = @PASSWORD@ - -string_mask = utf8only - -[ req_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = US -countryName_min = 2 -countryName_max = 2 - -localityName = Locality Name (eg, city) -localityName_default = Tuusula - -0.organizationName = Organization Name (eg, company) -0.organizationName_default = WFA Hotspot 2.0 - -##organizationalUnitName = Organizational Unit Name (eg, section) -#organizationalUnitName_default = -#@OU@ - -commonName = Common Name (e.g. server FQDN or YOUR name) -#@CN@ -commonName_max = 64 - -emailAddress = Email Address -emailAddress_max = 64 - -[ req_attributes ] - -[ v3_req ] - -# Extensions to add to a certificate request -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -subjectAltName=DNS:example.com,DNS:another.example.com - -[ v3_ca ] - -# Hotspot 2.0 PKI requirements -subjectKeyIdentifier=hash -basicConstraints = critical,CA:true -keyUsage = critical, cRLSign, keyCertSign - -[ crl_ext ] - -# issuerAltName=issuer:copy -authorityKeyIdentifier=keyid:always - -[ v3_OCSP ] - -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = OCSPSigning diff --git a/contrib/wpa/hs20/server/ca/openssl.cnf b/contrib/wpa/hs20/server/ca/openssl.cnf deleted file mode 100644 index 61410138340f..000000000000 --- a/contrib/wpa/hs20/server/ca/openssl.cnf +++ /dev/null @@ -1,200 +0,0 @@ -# OpenSSL configuration file for Hotspot 2.0 PKI (Intermediate CA) - -HOME = . -RANDFILE = $ENV::HOME/.rnd -oid_section = new_oids - -[ new_oids ] - -#logotypeoid=1.3.6.1.5.5.7.1.12 - -#################################################################### -[ ca ] -default_ca = CA_default # The default ca section - -#################################################################### -[ CA_default ] - -dir = ./demoCA # Where everything is kept -certs = $dir/certs # Where the issued certs are kept -crl_dir = $dir/crl # Where the issued crl are kept -database = $dir/index.txt # database index file. -#unique_subject = no # Set to 'no' to allow creation of - # several certificates with same subject -new_certs_dir = $dir/newcerts # default place for new certs. - -certificate = $dir/cacert.pem # The CA certificate -serial = $dir/serial # The current serial number -crlnumber = $dir/crlnumber # the current crl number - # must be commented out to leave a V1 CRL -crl = $dir/crl.pem # The current CRL -private_key = $dir/private/cakey.pem# The private key -RANDFILE = $dir/private/.rand # private random number file - -x509_extensions = ext_client # The extentions to add to the cert - -name_opt = ca_default # Subject Name options -cert_opt = ca_default # Certificate field options - -# Extension copying option: use with caution. -copy_extensions = copy - -default_days = 365 # how long to certify for -default_crl_days= 30 # how long before next CRL -default_md = default # use public key default MD -preserve = no # keep passed DN ordering - -policy = policy_match - -# For the CA policy -[ policy_match ] -countryName = supplied -stateOrProvinceName = optional -organizationName = supplied -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -[ policy_osu_server ] -countryName = match -stateOrProvinceName = optional -organizationName = match -organizationalUnitName = supplied -commonName = supplied -emailAddress = optional - -[ policy_anything ] -countryName = optional -stateOrProvinceName = optional -localityName = optional -organizationName = optional -organizationalUnitName = optional -commonName = supplied -emailAddress = optional - -#################################################################### -[ req ] -default_bits = 2048 -default_keyfile = privkey.pem -distinguished_name = req_distinguished_name -attributes = req_attributes -x509_extensions = v3_ca # The extentions to add to the self signed cert - -input_password = @PASSWORD@ -output_password = @PASSWORD@ - -string_mask = utf8only - -[ req_distinguished_name ] -countryName = Country Name (2 letter code) -countryName_default = FI -countryName_min = 2 -countryName_max = 2 - -localityName = Locality Name (eg, city) -localityName_default = Tuusula - -0.organizationName = Organization Name (eg, company) -0.organizationName_default = @DOMAIN@ - -##organizationalUnitName = Organizational Unit Name (eg, section) -#organizationalUnitName_default = -#@OU@ - -commonName = Common Name (e.g. server FQDN or YOUR name) -#@CN@ -commonName_max = 64 - -emailAddress = Email Address -emailAddress_max = 64 - -[ req_attributes ] - -[ v3_ca ] - -# Hotspot 2.0 PKI requirements -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid:always,issuer -basicConstraints = critical, CA:true, pathlen:0 -keyUsage = critical, cRLSign, keyCertSign -authorityInfoAccess = OCSP;URI:@OCSP_URI@ -# For SP intermediate CA -#subjectAltName=critical,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:engExample OSU -#nameConstraints=permitted;DNS:.@DOMAIN@ -#1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn - -[ v3_osu_server ] - -basicConstraints = critical, CA:true, pathlen:0 -keyUsage = critical, keyEncipherment -#@ALTNAME@ - -#logotypeoid=ASN1:SEQUENCE:LogotypeExtn -1.3.6.1.5.5.7.1.12=ASN1:SEQUENCE:LogotypeExtn -[LogotypeExtn] -communityLogos=EXP:0,SEQUENCE:LogotypeInfo -[LogotypeInfo] -# note: implicit tag converted to explicit for CHOICE -direct=EXP:0,SEQUENCE:LogotypeData -[LogotypeData] -image=SEQUENCE:LogotypeImage -[LogotypeImage] -imageDetails=SEQUENCE:LogotypeDetails -imageInfo=SEQUENCE:LogotypeImageInfo -[LogotypeDetails] -mediaType=IA5STRING:image/png -logotypeHash=SEQUENCE:HashAlgAndValues -logotypeURI=SEQUENCE:URI -[HashAlgAndValues] -value1=SEQUENCE:HashAlgAndValueSHA256 -#value2=SEQUENCE:HashAlgAndValueSHA1 -[HashAlgAndValueSHA256] -hashAlg=SEQUENCE:sha256_alg -hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH256@ -[HashAlgAndValueSHA1] -hashAlg=SEQUENCE:sha1_alg -hashValue=FORMAT:HEX,OCTETSTRING:@LOGO_HASH1@ -[sha256_alg] -algorithm=OID:sha256 -[sha1_alg] -algorithm=OID:sha1 -[URI] -uri=IA5STRING:@LOGO_URI@ -[LogotypeImageInfo] -# default value color(1), component optional -#type=IMP:0,INTEGER:1 -fileSize=INTEGER:7549 -xSize=INTEGER:128 -ySize=INTEGER:80 -language=IMP:4,IA5STRING:zxx - -[ crl_ext ] - -# issuerAltName=issuer:copy -authorityKeyIdentifier=keyid:always - -[ v3_OCSP ] - -basicConstraints = CA:FALSE -keyUsage = nonRepudiation, digitalSignature, keyEncipherment -extendedKeyUsage = OCSPSigning - -[ ext_client ] - -basicConstraints=CA:FALSE -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid,issuer -authorityInfoAccess = OCSP;URI:@OCSP_URI@ -#@ALTNAME@ -extendedKeyUsage = clientAuth - -[ ext_server ] - -# Hotspot 2.0 PKI requirements -basicConstraints=critical, CA:FALSE -subjectKeyIdentifier=hash -authorityKeyIdentifier=keyid,issuer -authorityInfoAccess = OCSP;URI:@OCSP_URI@ -#@ALTNAME@ -extendedKeyUsage = critical, serverAuth -keyUsage = critical, keyEncipherment diff --git a/contrib/wpa/hs20/server/ca/setup.sh b/contrib/wpa/hs20/server/ca/setup.sh deleted file mode 100755 index 78abcccff455..000000000000 --- a/contrib/wpa/hs20/server/ca/setup.sh +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/sh - -if [ -z "$OPENSSL" ]; then - OPENSSL=openssl -fi -export OPENSSL_CONF=$PWD/openssl.cnf -PASS=whatever -if [ -z "$DOMAIN" ]; then - DOMAIN=w1.fi -fi -COMPANY=w1.fi -OPER_ENG="engw1.fi TESTING USE" -OPER_FI="finw1.fi TESTIKÄYTTÖ" -CNR="Hotspot 2.0 Trust Root CA - 99" -CNO="ocsp.$DOMAIN" -CNV="osu-revoked.$DOMAIN" -CNOC="osu-client.$DOMAIN" -OSU_SERVER_HOSTNAME="osu.$DOMAIN" -DEBUG=0 -OCSP_URI="http://$CNO:8888/" -LOGO_URI="http://osu.w1.fi/w1fi_logo.png" -LOGO_HASH256="4532f7ec36424381617c03c6ce87b55a51d6e7177ffafda243cebf280a68954d" -LOGO_HASH1="5e1d5085676eede6b02da14d31c523ec20ffba0b" - -# Command line overrides -USAGE=$( cat < my-openssl-root.cnf - -cat openssl.cnf | sed "s/@PASSWORD@/$PASS/" | -sed "s,@OCSP_URI@,$OCSP_URI," | -sed "s,@LOGO_URI@,$LOGO_URI," | -sed "s,@LOGO_HASH1@,$LOGO_HASH1," | -sed "s,@LOGO_HASH256@,$LOGO_HASH256," | -sed "s/@DOMAIN@/$DOMAIN/" \ - > my-openssl.cnf - - -cat my-openssl-root.cnf | sed "s/#@CN@/commonName_default = $CNR/" > openssl.cnf.tmp -mkdir -p rootCA/certs rootCA/crl rootCA/newcerts rootCA/private -touch rootCA/index.txt -if [ -e rootCA/private/cakey.pem ]; then - echo " * Use existing Root CA" -else - echo " * Generate Root CA private key" - $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -keyout rootCA/private/cakey.pem -out rootCA/careq.pem || fail "Failed to generate Root CA private key" - echo " * Sign Root CA certificate" - $OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out rootCA/cacert.pem -days 10957 -batch -keyfile rootCA/private/cakey.pem -passin pass:$PASS -selfsign -extensions v3_ca -outdir rootCA/newcerts -infiles rootCA/careq.pem || fail "Failed to sign Root CA certificate" - $OPENSSL x509 -in rootCA/cacert.pem -out rootCA/cacert.der -outform DER || fail "Failed to create rootCA DER" - sha256sum rootCA/cacert.der > rootCA/cacert.fingerprint || fail "Failed to create rootCA fingerprint" -fi -if [ ! -e rootCA/crlnumber ]; then - echo 00 > rootCA/crlnumber -fi - -echo -echo "---[ Intermediate CA ]--------------------------------------------------" -echo - -cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $COMPANY Hotspot 2.0 Intermediate CA/" > openssl.cnf.tmp -mkdir -p demoCA/certs demoCA/crl demoCA/newcerts demoCA/private -touch demoCA/index.txt -if [ -e demoCA/private/cakey.pem ]; then - echo " * Use existing Intermediate CA" -else - echo " * Generate Intermediate CA private key" - $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -keyout demoCA/private/cakey.pem -out demoCA/careq.pem || fail "Failed to generate Intermediate CA private key" - echo " * Sign Intermediate CA certificate" - $OPENSSL ca -config openssl.cnf.tmp -md sha256 -create_serial -out demoCA/cacert.pem -days 3652 -batch -keyfile rootCA/private/cakey.pem -cert rootCA/cacert.pem -passin pass:$PASS -extensions v3_ca -infiles demoCA/careq.pem || fail "Failed to sign Intermediate CA certificate" - # horrible from security view point, but for testing purposes since OCSP responder does not seem to support -passin - openssl rsa -in demoCA/private/cakey.pem -out demoCA/private/cakey-plain.pem -passin pass:$PASS - $OPENSSL x509 -in demoCA/cacert.pem -out demoCA/cacert.der -outform DER || fail "Failed to create demoCA DER." - sha256sum demoCA/cacert.der > demoCA/cacert.fingerprint || fail "Failed to create demoCA fingerprint" -fi -if [ ! -e demoCA/crlnumber ]; then - echo 00 > demoCA/crlnumber -fi - -echo -echo "OCSP responder" -echo - -cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNO/" > openssl.cnf.tmp -$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out ocsp.csr -keyout ocsp.key -extensions v3_OCSP -$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -keyfile demoCA/private/cakey.pem -passin pass:$PASS -in ocsp.csr -out ocsp.pem -days 730 -extensions v3_OCSP || fail "Could not generate ocsp.pem" - -echo -echo "---[ Server - to be revoked ] ------------------------------------------" -echo - -cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNV/" > openssl.cnf.tmp -$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-revoked.csr -keyout server-revoked.key -$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-revoked.csr -out server-revoked.pem -key $PASS -days 730 -extensions ext_server -$OPENSSL ca -revoke server-revoked.pem -key $PASS - -echo -echo "---[ Server - with client ext key use ] ---------------------------------" -echo "---[ Only used for negative-testing for OSU-client implementation ] -----" -echo - -cat my-openssl.cnf | sed "s/#@CN@/commonName_default = $CNOC/" > openssl.cnf.tmp -$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out server-client.csr -keyout server-client.key || fail "Could not create server-client.key" -$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server-client.csr -out server-client.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create server-client.pem" - -echo -echo "---[ User ]-------------------------------------------------------------" -echo - -cat my-openssl.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp -$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -out user.csr -keyout user.key || fail "Could not create user.key" -$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in user.csr -out user.pem -key $PASS -days 730 -extensions ext_client || fail "Could not create user.pem" - -echo -echo "---[ Server ]-----------------------------------------------------------" -echo - -ALT="DNS:$OSU_SERVER_HOSTNAME" -ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_ENG" -ALT="$ALT,otherName:1.3.6.1.4.1.40808.1.1.1;UTF8String:$OPER_FI" - -cat my-openssl.cnf | - sed "s/#@CN@/commonName_default = $OSU_SERVER_HOSTNAME/" | - sed "s/^##organizationalUnitName/organizationalUnitName/" | - sed "s/#@OU@/organizationalUnitName_default = Hotspot 2.0 Online Sign Up Server/" | - sed "s/#@ALTNAME@/subjectAltName=critical,$ALT/" \ - > openssl.cnf.tmp -echo $OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server -$OPENSSL req -config $PWD/openssl.cnf.tmp -batch -sha256 -new -newkey rsa:2048 -nodes -out server.csr -keyout server.key -reqexts v3_osu_server || fail "Failed to generate server request" -$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -md sha256 -in server.csr -out server.pem -key $PASS -days 730 -extensions ext_server -policy policy_osu_server || fail "Failed to sign server certificate" - -#dump logotype details for debugging -$OPENSSL x509 -in server.pem -out server.der -outform DER -openssl asn1parse -in server.der -inform DER | grep HEX | tail -1 | sed 's/.*://' | xxd -r -p > logo.der -openssl asn1parse -in logo.der -inform DER > logo.asn1 - - -echo -echo "---[ CRL ]---------------------------------------------------------------" -echo - -$OPENSSL ca -config $PWD/my-openssl.cnf -gencrl -md sha256 -out demoCA/crl/crl.pem -passin pass:$PASS - -echo -echo "---[ Verify ]------------------------------------------------------------" -echo - -$OPENSSL verify -CAfile rootCA/cacert.pem demoCA/cacert.pem -$OPENSSL verify -CAfile rootCA/cacert.pem -untrusted demoCA/cacert.pem *.pem - -cat rootCA/cacert.pem demoCA/cacert.pem > ca.pem diff --git a/contrib/wpa/hs20/server/ca/w1fi_logo.png b/contrib/wpa/hs20/server/ca/w1fi_logo.png deleted file mode 100644 index ac7c259fff2e..000000000000 Binary files a/contrib/wpa/hs20/server/ca/w1fi_logo.png and /dev/null differ diff --git a/contrib/wpa/hs20/server/hs20-osu-server.txt b/contrib/wpa/hs20/server/hs20-osu-server.txt deleted file mode 100644 index 22478ad9d2cb..000000000000 --- a/contrib/wpa/hs20/server/hs20-osu-server.txt +++ /dev/null @@ -1,262 +0,0 @@ -Hotspot 2.0 OSU server -====================== - -The information in this document is based on the assumption that Ubuntu -16.04 server (64-bit) distribution is used and the web server is -Apache2. Neither of these are requirements for the installation, but if -other combinations are used, the package names and configuration -parameters may need to be adjusted. - -NOTE: This implementation and the example configuration here is meant -only for testing purposes in a lab environment. This design is not -secure to be installed in a publicly available Internet server without -considerable amount of modification and review for security issues. - - -Build dependencies ------------------- - -Ubuntu 16.04 server -- default installation -- upgraded to latest package versions - sudo apt-get update - sudo apt-get upgrade - -Packages needed for running the service: - sudo apt-get install sqlite3 - sudo apt-get install apache2 - sudo apt-get install php-sqlite3 php-xml libapache2-mod-php - -Additional packages needed for building the components: - sudo apt-get install build-essential - sudo apt-get install libsqlite3-dev - sudo apt-get install libssl-dev - sudo apt-get install libxml2-dev - - -Installation location ---------------------- - -Select a location for the installation root directory. The example here -assumes /home/user/hs20-server to be used, but this can be changed by -editing couple of files as indicated below. - -sudo mkdir -p /home/user/hs20-server -sudo chown $USER /home/user/hs20-server -mkdir -p /home/user/hs20-server/spp -mkdir -p /home/user/hs20-server/AS - - -Build ------ - -# hostapd as RADIUS server -cd hostapd - -#example build configuration -cat > .config < /home/user/hs20-server/terms-and-conditions <Terms and conditions..

-EOF - -# Build local keys and certs -cd ca -# Display help options. -./setup.sh -h - -# Remove old keys, fill in appropriate values, and generate your keys. -# For instance: -./clean.sh -rm -fr rootCA" -old_hostname=myserver.local -./setup.sh -C "Hotspot 2.0 Trust Root CA - CT" \ - -o $old_hostname-osu-client \ - -O $old_hostname-oscp -p lanforge -S $old_hostname \ - -V $old_hostname-osu-revoked \ - -m local -u http://$old_hostname:8888/ - -# Configure subscription policies -mkdir -p /home/user/hs20-server/spp/policy -cat > /home/user/hs20-server/spp/policy/default.xml < - - 30 - ClientInitiated - Unrestricted - https://policy-server.osu.example.com/hs20/spp.php - - -EOF - - -# Install Hotspot 2.0 SPP and OMA DM XML schema/DTD files - -# XML schema for SPP -# Copy the latest XML schema into /home/user/hs20-server/spp/spp.xsd - -# OMA DM Device Description Framework DTD -# Copy into /home/user/hs20-server/spp/dm_ddf-v1_2.dtd -# http://www.openmobilealliance.org/tech/DTD/dm_ddf-v1_2.dtd - - -# Configure RADIUS authentication service -# Note: Change the URL to match the setup -# Note: Install AAA server key/certificate and root CA in Key directory - -cat > /home/user/hs20-server/AS/as-sql.conf < /home/user/hs20-server/AS/as.radius_clients < - Options Indexes MultiViews FollowSymLinks - AllowOverride None - Require all granted - SSLOptions +StdEnvVars - - -Update SSL configuration to use the OSU server certificate/key. -They keys and certs are called 'server.key' and 'server.pem' from -ca/setup.sh. - -To support subscription remediation using client certificates, set -"SSLVerifyClient optional" and configure the trust root CA(s) for the -client certificates with SSLCACertificateFile. - -Enable default-ssl site and restart Apache2: - sudo a2ensite default-ssl - sudo a2enmod ssl - sudo service apache2 restart - - -Management UI -------------- - -The sample PHP scripts include a management UI for testing -purposes. That is available at https:///hs20/users.php - - -AP configuration ----------------- - -APs can now be configured to use the OSU server as the RADIUS -authentication server. In addition, the OSU Provider List ANQP element -should be configured to use the SPP (SOAP+XML) option and with the -following Server URL: -https:///hs20/spp.php/signup?realm=example.com diff --git a/contrib/wpa/hs20/server/hs20_spp_server.c b/contrib/wpa/hs20/server/hs20_spp_server.c deleted file mode 100644 index 347c40a73d6a..000000000000 --- a/contrib/wpa/hs20/server/hs20_spp_server.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Hotspot 2.0 SPP server - standalone version - * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" -#include -#include - -#include "common.h" -#include "common/version.h" -#include "xml-utils.h" -#include "spp_server.h" - - -static void write_timestamp(FILE *f) -{ - time_t t; - struct tm *tm; - - time(&t); - tm = localtime(&t); - - fprintf(f, "%04u-%02u-%02u %02u:%02u:%02u ", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); -} - - -void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...) -{ - va_list ap; - - if (ctx->debug_log == NULL) - return; - - write_timestamp(ctx->debug_log); - va_start(ap, fmt); - vfprintf(ctx->debug_log, fmt, ap); - va_end(ap); - - fprintf(ctx->debug_log, "\n"); -} - - -void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node) -{ - char *str; - - if (ctx->debug_log == NULL) - return; - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - - write_timestamp(ctx->debug_log); - fprintf(ctx->debug_log, "%s: '%s'\n", title, str); - os_free(str); -} - - -static int process(struct hs20_svc *ctx) -{ - int dmacc = 0; - xml_node_t *soap, *spp, *resp; - char *user, *realm, *post, *str; - - ctx->addr = getenv("HS20ADDR"); - if (ctx->addr) - debug_print(ctx, 1, "Connection from %s", ctx->addr); - ctx->test = getenv("HS20TEST"); - if (ctx->test) - debug_print(ctx, 1, "Requested test functionality: %s", - ctx->test); - - user = getenv("HS20USER"); - if (user && strlen(user) == 0) - user = NULL; - realm = getenv("HS20REALM"); - if (realm == NULL) { - debug_print(ctx, 1, "HS20REALM not set"); - return -1; - } - post = getenv("HS20POST"); - if (post == NULL) { - debug_print(ctx, 1, "HS20POST not set"); - return -1; - } - - ctx->imsi = getenv("HS20IMSI"); - if (ctx->imsi) - debug_print(ctx, 1, "IMSI %s", ctx->imsi); - - ctx->eap_method = getenv("HS20EAPMETHOD"); - if (ctx->eap_method) - debug_print(ctx, 1, "EAP method %s", ctx->eap_method); - - ctx->id_hash = getenv("HS20IDHASH"); - if (ctx->id_hash) - debug_print(ctx, 1, "ID-HASH %s", ctx->id_hash); - - soap = xml_node_from_buf(ctx->xml, post); - if (soap == NULL) { - debug_print(ctx, 1, "Could not parse SOAP data"); - return -1; - } - debug_dump_node(ctx, "Received SOAP message", soap); - spp = soap_get_body(ctx->xml, soap); - if (spp == NULL) { - debug_print(ctx, 1, "Could not get SPP message"); - xml_node_free(ctx->xml, soap); - return -1; - } - debug_dump_node(ctx, "Received SPP message", spp); - - resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc); - xml_node_free(ctx->xml, soap); - if (resp == NULL && user == NULL) { - debug_print(ctx, 1, "Request HTTP authentication"); - return 2; /* Request authentication */ - } - if (resp == NULL) { - debug_print(ctx, 1, "No response"); - return -1; - } - - soap = soap_build_envelope(ctx->xml, resp); - if (soap == NULL) { - debug_print(ctx, 1, "SOAP envelope building failed"); - return -1; - } - str = xml_node_to_str(ctx->xml, soap); - xml_node_free(ctx->xml, soap); - if (str == NULL) { - debug_print(ctx, 1, "Could not get node string"); - return -1; - } - printf("%s", str); - free(str); - - return 0; -} - - -static void usage(void) -{ - printf("usage:\n" - "hs20_spp_server -r [-f]\n"); -} - - -int main(int argc, char *argv[]) -{ - struct hs20_svc ctx; - int ret; - - os_memset(&ctx, 0, sizeof(ctx)); - for (;;) { - int c = getopt(argc, argv, "f:r:v"); - if (c < 0) - break; - switch (c) { - case 'f': - if (ctx.debug_log) - break; - ctx.debug_log = fopen(optarg, "a"); - if (ctx.debug_log == NULL) { - printf("Could not write to %s\n", optarg); - return -1; - } - break; - case 'r': - ctx.root_dir = optarg; - break; - case 'v': - printf("hs20_spp_server v%s\n", VERSION_STR); - return 0; - default: - usage(); - return -1; - } - } - if (ctx.root_dir == NULL) { - usage(); - return -1; - } - ctx.xml = xml_node_init_ctx(&ctx, NULL); - if (ctx.xml == NULL) - return -1; - if (hs20_spp_server_init(&ctx) < 0) { - xml_node_deinit_ctx(ctx.xml); - return -1; - } - - ret = process(&ctx); - debug_print(&ctx, 1, "process() --> %d", ret); - - xml_node_deinit_ctx(ctx.xml); - hs20_spp_server_deinit(&ctx); - if (ctx.debug_log) - fclose(ctx.debug_log); - - return ret; -} diff --git a/contrib/wpa/hs20/server/spp_server.c b/contrib/wpa/hs20/server/spp_server.c deleted file mode 100644 index a50e9074f7b4..000000000000 --- a/contrib/wpa/hs20/server/spp_server.c +++ /dev/null @@ -1,2933 +0,0 @@ -/* - * Hotspot 2.0 SPP server - * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "base64.h" -#include "md5_i.h" -#include "xml-utils.h" -#include "spp_server.h" - - -#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp" - -#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0" -#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0" -#define URN_OMA_DM_DMACC "urn:oma:mo:oma-dm-dmacc:1.0" -#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0" - - -/* TODO: timeout to expire sessions */ - -enum hs20_session_operation { - NO_OPERATION, - UPDATE_PASSWORD, - CONTINUE_SUBSCRIPTION_REMEDIATION, - CONTINUE_POLICY_UPDATE, - USER_REMEDIATION, - SUBSCRIPTION_REGISTRATION, - POLICY_REMEDIATION, - POLICY_UPDATE, - FREE_REMEDIATION, - CLEAR_REMEDIATION, - CERT_REENROLL, -}; - - -static char * db_get_session_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *session_id, - const char *field); -static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, - const char *field); -static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, - const char *realm, int use_dmacc); -static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, - const char *session_id, - const char *user, - const char *realm, - int add_est_user); - - -static int db_add_session(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid, const char *pw, - const char *redirect_uri, - enum hs20_session_operation operation, - const u8 *mac_addr) -{ - char *sql; - int ret = 0; - char addr[20]; - - if (mac_addr) - snprintf(addr, sizeof(addr), MACSTR, MAC2STR(mac_addr)); - else - addr[0] = '\0'; - sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm," - "operation,password,redirect_uri,mac_addr,test) " - "VALUES " - "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," - "%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", - sessionid, user ? user : "", realm ? realm : "", - operation, pw ? pw : "", - redirect_uri ? redirect_uri : "", - addr, ctx->test); - if (sql == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session entry into sqlite " - "database: %s", sqlite3_errmsg(ctx->db)); - ret = -1; - } - sqlite3_free(sql); - return ret; -} - - -static void db_update_session_password(struct hs20_svc *ctx, const char *user, - const char *realm, const char *sessionid, - const char *pw) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET password=%Q WHERE id=%Q AND " - "user=%Q AND realm=%Q", - pw, sessionid, user, realm); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update session password: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_update_session_machine_managed(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *sessionid, - const int pw_mm) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET machine_managed=%Q WHERE id=%Q AND user=%Q AND realm=%Q", - pw_mm ? "1" : "0", sessionid, user, realm); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, - "Failed to update session machine_managed: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_pps(struct hs20_svc *ctx, const char *user, - const char *realm, const char *sessionid, - xml_node_t *node) -{ - char *str; - char *sql; - - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - sql = sqlite3_mprintf("UPDATE sessions SET pps=%Q WHERE id=%Q AND " - "user=%Q AND realm=%Q", - str, sessionid, user, realm); - free(str); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session pps: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_devinfo(struct hs20_svc *ctx, const char *sessionid, - xml_node_t *node) -{ - char *str; - char *sql; - - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - sql = sqlite3_mprintf("UPDATE sessions SET devinfo=%Q WHERE id=%Q", - str, sessionid); - free(str); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session devinfo: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_devdetail(struct hs20_svc *ctx, - const char *sessionid, - xml_node_t *node) -{ - char *str; - char *sql; - - str = xml_node_to_str(ctx->xml, node); - if (str == NULL) - return; - sql = sqlite3_mprintf("UPDATE sessions SET devdetail=%Q WHERE id=%Q", - str, sessionid); - free(str); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session devdetail: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_dmacc(struct hs20_svc *ctx, const char *sessionid, - const char *username, const char *password) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET osu_user=%Q, osu_password=%Q WHERE id=%Q", - username, password, sessionid); - if (!sql) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session DMAcc: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_eap_method(struct hs20_svc *ctx, - const char *sessionid, - const char *method) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET eap_method=%Q WHERE id=%Q", - method, sessionid); - if (!sql) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session EAP method: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_add_session_id_hash(struct hs20_svc *ctx, const char *sessionid, - const char *id_hash) -{ - char *sql; - - sql = sqlite3_mprintf("UPDATE sessions SET mobile_identifier_hash=%Q WHERE id=%Q", - id_hash, sessionid); - if (!sql) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add session ID hash: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_remove_session(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid) -{ - char *sql; - - if (user == NULL || realm == NULL) { - sql = sqlite3_mprintf("DELETE FROM sessions WHERE " - "id=%Q", sessionid); - } else { - sql = sqlite3_mprintf("DELETE FROM sessions WHERE " - "user=%Q AND realm=%Q AND id=%Q", - user, realm, sessionid); - } - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to delete session entry from " - "sqlite database: %s", sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void hs20_eventlog(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid, const char *notes, - const char *dump) -{ - char *sql; - char *user_buf = NULL, *realm_buf = NULL; - - debug_print(ctx, 1, "eventlog: %s", notes); - - if (user == NULL) { - user_buf = db_get_session_val(ctx, NULL, NULL, sessionid, - "user"); - user = user_buf; - realm_buf = db_get_session_val(ctx, NULL, NULL, sessionid, - "realm"); - realm = realm_buf; - } - - sql = sqlite3_mprintf("INSERT INTO eventlog" - "(user,realm,sessionid,timestamp,notes,dump,addr)" - " VALUES (%Q,%Q,%Q," - "strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," - "%Q,%Q,%Q)", - user, realm, sessionid, notes, - dump ? dump : "", ctx->addr ? ctx->addr : ""); - free(user_buf); - free(realm_buf); - if (sql == NULL) - return; - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add eventlog entry into sqlite " - "database: %s", sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void hs20_eventlog_node(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *sessionid, const char *notes, - xml_node_t *node) -{ - char *str; - - if (node) - str = xml_node_to_str(ctx->xml, node); - else - str = NULL; - hs20_eventlog(ctx, user, realm, sessionid, notes, str); - free(str); -} - - -static void db_update_mo_str(struct hs20_svc *ctx, const char *user, - const char *realm, const char *name, - const char *str) -{ - char *sql; - if (user == NULL || realm == NULL || name == NULL) - return; - sql = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE identity=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - name, str, user, realm); - if (sql == NULL) - return; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update user MO entry in sqlite " - "database: %s", sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); -} - - -static void db_update_mo(struct hs20_svc *ctx, const char *user, - const char *realm, const char *name, xml_node_t *mo) -{ - char *str; - - str = xml_node_to_str(ctx->xml, mo); - if (str == NULL) - return; - - db_update_mo_str(ctx, user, realm, name, str); - free(str); -} - - -static void add_text_node(struct hs20_svc *ctx, xml_node_t *parent, - const char *name, const char *value) -{ - xml_node_create_text(ctx->xml, parent, NULL, name, value ? value : ""); -} - - -static void add_text_node_conf(struct hs20_svc *ctx, const char *realm, - xml_node_t *parent, const char *name, - const char *field) -{ - char *val; - val = db_get_osu_config_val(ctx, realm, field); - xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); - os_free(val); -} - - -static void add_text_node_conf_corrupt(struct hs20_svc *ctx, const char *realm, - xml_node_t *parent, const char *name, - const char *field) -{ - char *val; - - val = db_get_osu_config_val(ctx, realm, field); - if (val) { - size_t len; - - len = os_strlen(val); - if (len > 0) { - if (val[len - 1] == '0') - val[len - 1] = '1'; - else - val[len - 1] = '0'; - } - } - xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); - os_free(val); -} - - -static int new_password(char *buf, int buflen) -{ - int i; - - if (buflen < 1) - return -1; - buf[buflen - 1] = '\0'; - if (os_get_random((unsigned char *) buf, buflen - 1) < 0) - return -1; - - for (i = 0; i < buflen - 1; i++) { - unsigned char val = buf[i]; - val %= 2 * 26 + 10; - if (val < 26) - buf[i] = 'a' + val; - else if (val < 2 * 26) - buf[i] = 'A' + val - 26; - else - buf[i] = '0' + val - 2 * 26; - } - - return 0; -} - - -struct get_db_field_data { - const char *field; - char *value; -}; - - -static int get_db_field(void *ctx, int argc, char *argv[], char *col[]) -{ - struct get_db_field_data *data = ctx; - int i; - - for (i = 0; i < argc; i++) { - if (os_strcmp(col[i], data->field) == 0 && argv[i]) { - os_free(data->value); - data->value = os_strdup(argv[i]); - break; - } - } - - return 0; -} - - -static char * db_get_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *field, int dmacc) -{ - char *cmd; - struct get_db_field_data data; - - cmd = sqlite3_mprintf("SELECT %s FROM users WHERE %s=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - field, dmacc ? "osu_user" : "identity", - user, realm); - if (cmd == NULL) - return NULL; - memset(&data, 0, sizeof(data)); - data.field = field; - if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) - { - debug_print(ctx, 1, "Could not find user '%s'", user); - sqlite3_free(cmd); - return NULL; - } - sqlite3_free(cmd); - - debug_print(ctx, 1, "DB: user='%s' realm='%s' field='%s' dmacc=%d --> " - "value='%s'", user, realm, field, dmacc, data.value); - - return data.value; -} - - -static int db_update_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *field, - const char *val, int dmacc) -{ - char *cmd; - int ret; - - cmd = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE %s=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - field, val, dmacc ? "osu_user" : "identity", user, - realm); - if (cmd == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", cmd); - if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, - "Failed to update user in sqlite database: %s", - sqlite3_errmsg(ctx->db)); - ret = -1; - } else { - debug_print(ctx, 1, - "DB: user='%s' realm='%s' field='%s' set to '%s'", - user, realm, field, val); - ret = 0; - } - sqlite3_free(cmd); - - return ret; -} - - -static char * db_get_session_val(struct hs20_svc *ctx, const char *user, - const char *realm, const char *session_id, - const char *field) -{ - char *cmd; - struct get_db_field_data data; - - if (user == NULL || realm == NULL) { - cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " - "id=%Q", field, session_id); - } else { - cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " - "user=%Q AND realm=%Q AND id=%Q", - field, user, realm, session_id); - } - if (cmd == NULL) - return NULL; - debug_print(ctx, 1, "DB: %s", cmd); - memset(&data, 0, sizeof(data)); - data.field = field; - if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) - { - debug_print(ctx, 1, "DB: Could not find session %s: %s", - session_id, sqlite3_errmsg(ctx->db)); - sqlite3_free(cmd); - return NULL; - } - sqlite3_free(cmd); - - debug_print(ctx, 1, "DB: return '%s'", data.value); - return data.value; -} - - -static int update_password(struct hs20_svc *ctx, const char *user, - const char *realm, const char *pw, int dmacc) -{ - char *cmd; - - cmd = sqlite3_mprintf("UPDATE users SET password=%Q, " - "remediation='' " - "WHERE %s=%Q AND phase2=1", - pw, dmacc ? "osu_user" : "identity", - user); - if (cmd == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", cmd); - if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update database for user '%s'", - user); - } - sqlite3_free(cmd); - - return 0; -} - - -static int clear_remediation(struct hs20_svc *ctx, const char *user, - const char *realm, int dmacc) -{ - char *cmd; - - cmd = sqlite3_mprintf("UPDATE users SET remediation='' WHERE %s=%Q", - dmacc ? "osu_user" : "identity", - user); - if (cmd == NULL) - return -1; - debug_print(ctx, 1, "DB: %s", cmd); - if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update database for user '%s'", - user); - } - sqlite3_free(cmd); - - return 0; -} - - -static int add_eap_ttls(struct hs20_svc *ctx, xml_node_t *parent) -{ - xml_node_t *node; - - node = xml_node_create(ctx->xml, parent, NULL, "EAPMethod"); - if (node == NULL) - return -1; - - add_text_node(ctx, node, "EAPType", "21"); - add_text_node(ctx, node, "InnerMethod", "MS-CHAP-V2"); - - return 0; -} - - -static xml_node_t * build_username_password(struct hs20_svc *ctx, - xml_node_t *parent, - const char *user, const char *pw) -{ - xml_node_t *node; - char *b64; - size_t len; - - node = xml_node_create(ctx->xml, parent, NULL, "UsernamePassword"); - if (node == NULL) - return NULL; - - add_text_node(ctx, node, "Username", user); - - b64 = base64_encode(pw, strlen(pw), NULL); - if (b64 == NULL) - return NULL; - len = os_strlen(b64); - if (len > 0 && b64[len - 1] == '\n') - b64[len - 1] = '\0'; - add_text_node(ctx, node, "Password", b64); - free(b64); - - return node; -} - - -static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred, - const char *user, const char *pw, - int machine_managed) -{ - xml_node_t *node; - - node = build_username_password(ctx, cred, user, pw); - if (node == NULL) - return -1; - - add_text_node(ctx, node, "MachineManaged", - machine_managed ? "TRUE" : "FALSE"); - add_text_node(ctx, node, "SoftTokenApp", ""); - add_eap_ttls(ctx, node); - - return 0; -} - - -static void add_creation_date(struct hs20_svc *ctx, xml_node_t *cred) -{ - char str[30]; - time_t now; - struct tm tm; - - time(&now); - gmtime_r(&now, &tm); - snprintf(str, sizeof(str), "%04u-%02u-%02uT%02u:%02u:%02uZ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - xml_node_create_text(ctx->xml, cred, NULL, "CreationDate", str); -} - - -static xml_node_t * build_credential_pw(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *pw, int machine_managed) -{ - xml_node_t *cred; - - cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); - if (cred == NULL) { - debug_print(ctx, 1, "Failed to create Credential node"); - return NULL; - } - add_creation_date(ctx, cred); - if (add_username_password(ctx, cred, user, pw, machine_managed) < 0) { - xml_node_free(ctx->xml, cred); - return NULL; - } - add_text_node(ctx, cred, "Realm", realm); - - return cred; -} - - -static xml_node_t * build_credential(struct hs20_svc *ctx, - const char *user, const char *realm, - char *new_pw, size_t new_pw_len) -{ - if (new_password(new_pw, new_pw_len) < 0) - return NULL; - debug_print(ctx, 1, "Update password to '%s'", new_pw); - return build_credential_pw(ctx, user, realm, new_pw, 1); -} - - -static xml_node_t * build_credential_cert(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *cert_fingerprint) -{ - xml_node_t *cred, *cert; - - cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); - if (cred == NULL) { - debug_print(ctx, 1, "Failed to create Credential node"); - return NULL; - } - add_creation_date(ctx, cred); - cert = xml_node_create(ctx->xml, cred, NULL, "DigitalCertificate"); - add_text_node(ctx, cert, "CertificateType", "x509v3"); - add_text_node(ctx, cert, "CertSHA256Fingerprint", cert_fingerprint); - add_text_node(ctx, cred, "Realm", realm); - - return cred; -} - - -static xml_node_t * build_post_dev_data_response(struct hs20_svc *ctx, - xml_namespace_t **ret_ns, - const char *session_id, - const char *status, - const char *error_code) -{ - xml_node_t *spp_node = NULL; - xml_namespace_t *ns; - - spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, - "sppPostDevDataResponse"); - if (spp_node == NULL) - return NULL; - if (ret_ns) - *ret_ns = ns; - - xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); - xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); - xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); - - if (error_code) { - xml_node_t *node; - node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); - if (node) - xml_node_add_attr(ctx->xml, node, NULL, "errorCode", - error_code); - } - - return spp_node; -} - - -static int add_update_node(struct hs20_svc *ctx, xml_node_t *spp_node, - xml_namespace_t *ns, const char *uri, - xml_node_t *upd_node) -{ - xml_node_t *node, *tnds; - char *str; - - tnds = mo_to_tnds(ctx->xml, upd_node, 0, NULL, NULL); - if (!tnds) - return -1; - - str = xml_node_to_str(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (str == NULL) - return -1; - node = xml_node_create_text(ctx->xml, spp_node, ns, "updateNode", str); - free(str); - - xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", uri); - - return 0; -} - - -static xml_node_t * read_subrem_file(struct hs20_svc *ctx, - const char *subrem_id, - char *uri, size_t uri_size) -{ - char fname[200]; - char *buf, *buf2, *pos; - size_t len; - xml_node_t *node; - - os_snprintf(fname, sizeof(fname), "%s/spp/subrem/%s", - ctx->root_dir, subrem_id); - debug_print(ctx, 1, "Use subrem file %s", fname); - - buf = os_readfile(fname, &len); - if (!buf) - return NULL; - buf2 = os_realloc(buf, len + 1); - if (!buf2) { - os_free(buf); - return NULL; - } - buf = buf2; - buf[len] = '\0'; - - pos = os_strchr(buf, '\n'); - if (!pos) { - os_free(buf); - return NULL; - } - *pos++ = '\0'; - os_strlcpy(uri, buf, uri_size); - - node = xml_node_from_buf(ctx->xml, pos); - os_free(buf); - - return node; -} - - -static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, - int machine_rem, int dmacc) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *cred; - char buf[400]; - char new_pw[33]; - char *status; - char *cert; - - cert = db_get_val(ctx, user, realm, "cert", dmacc); - if (cert && cert[0] == '\0') { - os_free(cert); - cert = NULL; - } - if (cert) { - char *subrem; - - /* No change needed in PPS MO unless specifically asked to */ - cred = NULL; - buf[0] = '\0'; - - subrem = db_get_val(ctx, user, realm, "subrem", dmacc); - if (subrem && subrem[0]) { - cred = read_subrem_file(ctx, subrem, buf, sizeof(buf)); - if (!cred) { - debug_print(ctx, 1, - "Could not create updateNode from subrem file"); - os_free(subrem); - os_free(cert); - return NULL; - } - } - os_free(subrem); - } else { - char *real_user = NULL; - char *pw; - - if (dmacc) { - real_user = db_get_val(ctx, user, realm, "identity", - dmacc); - if (!real_user) { - debug_print(ctx, 1, - "Could not find user identity for dmacc user '%s'", - user); - return NULL; - } - } - - pw = db_get_session_val(ctx, user, realm, session_id, - "password"); - if (pw && pw[0]) { - debug_print(ctx, 1, "New password from the user: '%s'", - pw); - snprintf(new_pw, sizeof(new_pw), "%s", pw); - free(pw); - cred = build_credential_pw(ctx, - real_user ? real_user : user, - realm, new_pw, 0); - } else { - cred = build_credential(ctx, - real_user ? real_user : user, - realm, new_pw, sizeof(new_pw)); - } - - free(real_user); - if (!cred) { - debug_print(ctx, 1, "Could not build credential"); - os_free(cert); - return NULL; - } - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", - realm); - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) { - debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); - os_free(cert); - return NULL; - } - - if ((cred && add_update_node(ctx, spp_node, ns, buf, cred) < 0) || - (!cred && !xml_node_create(ctx->xml, spp_node, ns, "noMOUpdate"))) { - debug_print(ctx, 1, "Could not add update node"); - xml_node_free(ctx->xml, spp_node); - os_free(cert); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - machine_rem ? "machine remediation" : - "user remediation", cred); - xml_node_free(ctx->xml, cred); - - if (cert) { - debug_print(ctx, 1, "Request DB remediation clearing on success notification (certificate credential)"); - db_add_session(ctx, user, realm, session_id, NULL, NULL, - CLEAR_REMEDIATION, NULL); - } else { - debug_print(ctx, 1, "Request DB password update on success " - "notification"); - db_add_session(ctx, user, realm, session_id, new_pw, NULL, - UPDATE_PASSWORD, NULL); - } - os_free(cert); - - return spp_node; -} - - -static xml_node_t * machine_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id, int dmacc) -{ - return build_sub_rem_resp(ctx, user, realm, session_id, 1, dmacc); -} - - -static xml_node_t * cert_reenroll(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id) -{ - db_add_session(ctx, user, realm, session_id, NULL, NULL, - CERT_REENROLL, NULL); - return spp_exec_get_certificate(ctx, session_id, user, realm, 0); -} - - -static xml_node_t * policy_remediation(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, int dmacc) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *policy; - char buf[400]; - const char *status; - - hs20_eventlog(ctx, user, realm, session_id, - "requires policy remediation", NULL); - - db_add_session(ctx, user, realm, session_id, NULL, NULL, - POLICY_REMEDIATION, NULL); - - policy = build_policy(ctx, user, realm, dmacc); - if (!policy) { - return build_post_dev_data_response( - ctx, NULL, session_id, - "No update available at this time", NULL); - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { - xml_node_free(ctx->xml, spp_node); - xml_node_free(ctx->xml, policy); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "policy update (sub rem)", policy); - xml_node_free(ctx->xml, policy); - - return spp_node; -} - - -static xml_node_t * browser_remediation(struct hs20_svc *ctx, - const char *session_id, - const char *redirect_uri, - const char *uri) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *exec_node; - - if (redirect_uri == NULL) { - debug_print(ctx, 1, "Missing redirectURI attribute for user " - "remediation"); - return NULL; - } - debug_print(ctx, 1, "redirectURI %s", redirect_uri); - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", - uri); - return spp_node; -} - - -static xml_node_t * user_remediation(struct hs20_svc *ctx, const char *user, - const char *realm, const char *session_id, - const char *redirect_uri) -{ - char uri[300], *val; - - hs20_eventlog(ctx, user, realm, session_id, - "requires user remediation", NULL); - val = db_get_osu_config_val(ctx, realm, "remediation_url"); - if (val == NULL) - return NULL; - - db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, - USER_REMEDIATION, NULL); - - snprintf(uri, sizeof(uri), "%s%s", val, session_id); - os_free(val); - return browser_remediation(ctx, session_id, redirect_uri, uri); -} - - -static xml_node_t * free_remediation(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, - const char *redirect_uri) -{ - char uri[300], *val; - - hs20_eventlog(ctx, user, realm, session_id, - "requires free/public account remediation", NULL); - val = db_get_osu_config_val(ctx, realm, "free_remediation_url"); - if (val == NULL) - return NULL; - - db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, - FREE_REMEDIATION, NULL); - - snprintf(uri, sizeof(uri), "%s%s", val, session_id); - os_free(val); - return browser_remediation(ctx, session_id, redirect_uri, uri); -} - - -static xml_node_t * no_sub_rem(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id) -{ - const char *status; - - hs20_eventlog(ctx, user, realm, session_id, - "no subscription mediation available", NULL); - - status = "No update available at this time"; - return build_post_dev_data_response(ctx, NULL, session_id, status, - NULL); -} - - -static xml_node_t * hs20_subscription_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id, - int dmacc, - const char *redirect_uri) -{ - char *type, *identity; - xml_node_t *ret; - char *free_account; - - identity = db_get_val(ctx, user, realm, "identity", dmacc); - if (identity == NULL || strlen(identity) == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "user not found in database for remediation", - NULL); - os_free(identity); - return build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", - "Not found"); - } - os_free(identity); - - free_account = db_get_osu_config_val(ctx, realm, "free_account"); - if (free_account && strcmp(free_account, user) == 0) { - free(free_account); - return no_sub_rem(ctx, user, realm, session_id); - } - free(free_account); - - type = db_get_val(ctx, user, realm, "remediation", dmacc); - if (type && strcmp(type, "free") != 0) { - char *val; - int shared = 0; - val = db_get_val(ctx, user, realm, "shared", dmacc); - if (val) - shared = atoi(val); - free(val); - if (shared) { - free(type); - return no_sub_rem(ctx, user, realm, session_id); - } - } - if (type && strcmp(type, "user") == 0) - ret = user_remediation(ctx, user, realm, session_id, - redirect_uri); - else if (type && strcmp(type, "free") == 0) - ret = free_remediation(ctx, user, realm, session_id, - redirect_uri); - else if (type && strcmp(type, "policy") == 0) - ret = policy_remediation(ctx, user, realm, session_id, dmacc); - else if (type && strcmp(type, "machine") == 0) - ret = machine_remediation(ctx, user, realm, session_id, dmacc); - else if (type && strcmp(type, "reenroll") == 0) - ret = cert_reenroll(ctx, user, realm, session_id); - else - ret = no_sub_rem(ctx, user, realm, session_id); - free(type); - - return ret; -} - - -static xml_node_t * read_policy_file(struct hs20_svc *ctx, - const char *policy_id) -{ - char fname[200]; - - snprintf(fname, sizeof(fname), "%s/spp/policy/%s.xml", - ctx->root_dir, policy_id); - debug_print(ctx, 1, "Use policy file %s", fname); - - return node_from_file(ctx->xml, fname); -} - - -static void update_policy_update_uri(struct hs20_svc *ctx, const char *realm, - xml_node_t *policy) -{ - xml_node_t *node; - char *url; - - node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate/URI"); - if (!node) - return; - - url = db_get_osu_config_val(ctx, realm, "policy_url"); - if (!url) - return; - xml_node_set_text(ctx->xml, node, url); - free(url); -} - - -static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, - const char *realm, int use_dmacc) -{ - char *policy_id; - xml_node_t *policy, *node; - - policy_id = db_get_val(ctx, user, realm, "policy", use_dmacc); - if (policy_id == NULL || strlen(policy_id) == 0) { - free(policy_id); - policy_id = strdup("default"); - if (policy_id == NULL) - return NULL; - } - policy = read_policy_file(ctx, policy_id); - free(policy_id); - if (policy == NULL) - return NULL; - - update_policy_update_uri(ctx, realm, policy); - - node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate"); - if (node && use_dmacc) { - char *pw; - pw = db_get_val(ctx, user, realm, "osu_password", use_dmacc); - if (pw == NULL || - build_username_password(ctx, node, user, pw) == NULL) { - debug_print(ctx, 1, "Failed to add Policy/PolicyUpdate/" - "UsernamePassword"); - free(pw); - xml_node_free(ctx->xml, policy); - return NULL; - } - free(pw); - } - - return policy; -} - - -static xml_node_t * hs20_policy_update(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *session_id, int dmacc) -{ - xml_namespace_t *ns; - xml_node_t *spp_node; - xml_node_t *policy; - char buf[400]; - const char *status; - char *identity; - - identity = db_get_val(ctx, user, realm, "identity", dmacc); - if (identity == NULL || strlen(identity) == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "user not found in database for policy update", - NULL); - os_free(identity); - return build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", - "Not found"); - } - os_free(identity); - - policy = build_policy(ctx, user, realm, dmacc); - if (!policy) { - return build_post_dev_data_response( - ctx, NULL, session_id, - "No update available at this time", NULL); - } - - db_add_session(ctx, user, realm, session_id, NULL, NULL, POLICY_UPDATE, - NULL); - - status = "Update complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { - xml_node_free(ctx->xml, spp_node); - xml_node_free(ctx->xml, policy); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, "policy update", - policy); - xml_node_free(ctx->xml, policy); - - return spp_node; -} - - -static xml_node_t * spp_get_mo(struct hs20_svc *ctx, xml_node_t *node, - const char *urn, int *valid, char **ret_err) -{ - xml_node_t *child, *tnds, *mo; - const char *name; - char *mo_urn; - char *str; - char fname[200]; - - *valid = -1; - if (ret_err) - *ret_err = NULL; - - xml_node_for_each_child(ctx->xml, child, node) { - xml_node_for_each_check(ctx->xml, child); - name = xml_node_get_localname(ctx->xml, child); - if (strcmp(name, "moContainer") != 0) - continue; - mo_urn = xml_node_get_attr_value_ns(ctx->xml, child, SPP_NS_URI, - "moURN"); - if (strcasecmp(urn, mo_urn) == 0) { - xml_node_get_attr_value_free(ctx->xml, mo_urn); - break; - } - xml_node_get_attr_value_free(ctx->xml, mo_urn); - } - - if (child == NULL) - return NULL; - - debug_print(ctx, 1, "moContainer text for %s", urn); - debug_dump_node(ctx, "moContainer", child); - - str = xml_node_get_text(ctx->xml, child); - debug_print(ctx, 1, "moContainer payload: '%s'", str); - tnds = xml_node_from_buf(ctx->xml, str); - xml_node_get_text_free(ctx->xml, str); - if (tnds == NULL) { - debug_print(ctx, 1, "could not parse moContainer text"); - return NULL; - } - - snprintf(fname, sizeof(fname), "%s/spp/dm_ddf-v1_2.dtd", ctx->root_dir); - if (xml_validate_dtd(ctx->xml, tnds, fname, ret_err) == 0) - *valid = 1; - else if (ret_err && *ret_err && - os_strcmp(*ret_err, "No declaration for attribute xmlns of element MgmtTree\n") == 0) { - free(*ret_err); - debug_print(ctx, 1, "Ignore OMA-DM DDF DTD validation error for MgmtTree namespace declaration with xmlns attribute"); - *ret_err = NULL; - *valid = 1; - } else - *valid = 0; - - mo = tnds_to_mo(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (mo == NULL) { - debug_print(ctx, 1, "invalid moContainer for %s", urn); - } - - return mo; -} - - -static xml_node_t * spp_exec_upload_mo(struct hs20_svc *ctx, - const char *session_id, const char *urn) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node, *exec_node; - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - - node = xml_node_create(ctx->xml, exec_node, ns, "uploadMO"); - xml_node_add_attr(ctx->xml, node, ns, "moURN", urn); - - return spp_node; -} - - -static xml_node_t * hs20_subscription_registration(struct hs20_svc *ctx, - const char *realm, - const char *session_id, - const char *redirect_uri, - const u8 *mac_addr) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *exec_node; - char uri[300], *val; - - if (db_add_session(ctx, NULL, realm, session_id, NULL, redirect_uri, - SUBSCRIPTION_REGISTRATION, mac_addr) < 0) - return NULL; - val = db_get_osu_config_val(ctx, realm, "signup_url"); - if (val == NULL) - return NULL; - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - - snprintf(uri, sizeof(uri), "%s%s", val, session_id); - os_free(val); - xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", - uri); - return spp_node; -} - - -static xml_node_t * hs20_user_input_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - return build_sub_rem_resp(ctx, user, realm, session_id, 0, dmacc); -} - - -static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, - const char *field) -{ - char *cmd; - struct get_db_field_data data; - - cmd = sqlite3_mprintf("SELECT value FROM osu_config WHERE realm=%Q AND " - "field=%Q", realm, field); - if (cmd == NULL) - return NULL; - debug_print(ctx, 1, "DB: %s", cmd); - memset(&data, 0, sizeof(data)); - data.field = "value"; - if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) - { - debug_print(ctx, 1, "DB: Could not find osu_config %s: %s", - realm, sqlite3_errmsg(ctx->db)); - sqlite3_free(cmd); - return NULL; - } - sqlite3_free(cmd); - - debug_print(ctx, 1, "DB: return '%s'", data.value); - return data.value; -} - - -static xml_node_t * build_pps(struct hs20_svc *ctx, - const char *user, const char *realm, - const char *pw, const char *cert, - int machine_managed, const char *test, - const char *imsi, const char *dmacc_username, - const char *dmacc_password, - xml_node_t *policy_node) -{ - xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp, *p; - xml_node_t *cred, *eap, *userpw; - - pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "PerProviderSubscription"); - if (!pps) { - xml_node_free(ctx->xml, policy_node); - return NULL; - } - - add_text_node(ctx, pps, "UpdateIdentifier", "1"); - - c = xml_node_create(ctx->xml, pps, NULL, "Cred01"); - - add_text_node(ctx, c, "CredentialPriority", "1"); - - if (imsi) - goto skip_aaa_trust_root; - aaa = xml_node_create(ctx->xml, c, NULL, "AAAServerTrustRoot"); - aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1"); - add_text_node_conf(ctx, realm, aaa1, "CertURL", - "aaa_trust_root_cert_url"); - if (test && os_strcmp(test, "corrupt_aaa_hash") == 0) { - debug_print(ctx, 1, - "TEST: Corrupt PPS/Cred*/AAAServerTrustRoot/Root*/CertSHA256FingerPrint"); - add_text_node_conf_corrupt(ctx, realm, aaa1, - "CertSHA256Fingerprint", - "aaa_trust_root_cert_fingerprint"); - } else { - add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint", - "aaa_trust_root_cert_fingerprint"); - } - - if (test && os_strcmp(test, "corrupt_polupd_hash") == 0) { - debug_print(ctx, 1, - "TEST: Corrupt PPS/Cred*/Policy/PolicyUpdate/Trustroot/CertSHA256FingerPrint"); - p = xml_node_create(ctx->xml, c, NULL, "Policy"); - upd = xml_node_create(ctx->xml, p, NULL, "PolicyUpdate"); - add_text_node(ctx, upd, "UpdateInterval", "30"); - add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated"); - add_text_node(ctx, upd, "Restriction", "Unrestricted"); - add_text_node_conf(ctx, realm, upd, "URI", "policy_url"); - trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); - add_text_node_conf(ctx, realm, trust, "CertURL", - "policy_trust_root_cert_url"); - add_text_node_conf_corrupt(ctx, realm, trust, - "CertSHA256Fingerprint", - "policy_trust_root_cert_fingerprint"); - } -skip_aaa_trust_root: - - upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate"); - add_text_node(ctx, upd, "UpdateInterval", "4294967295"); - add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated"); - add_text_node(ctx, upd, "Restriction", "HomeSP"); - add_text_node_conf(ctx, realm, upd, "URI", "spp_http_auth_url"); - trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); - add_text_node_conf(ctx, realm, trust, "CertURL", "trust_root_cert_url"); - if (test && os_strcmp(test, "corrupt_subrem_hash") == 0) { - debug_print(ctx, 1, - "TEST: Corrupt PPS/Cred*/SubscriptionUpdate/Trustroot/CertSHA256FingerPrint"); - add_text_node_conf_corrupt(ctx, realm, trust, - "CertSHA256Fingerprint", - "trust_root_cert_fingerprint"); - } else { - add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint", - "trust_root_cert_fingerprint"); - } - - if (dmacc_username && - !build_username_password(ctx, upd, dmacc_username, - dmacc_password)) { - xml_node_free(ctx->xml, pps); - xml_node_free(ctx->xml, policy_node); - return NULL; - } - - if (policy_node) - xml_node_add_child(ctx->xml, c, policy_node); - - homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP"); - add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name"); - add_text_node_conf(ctx, realm, homesp, "FQDN", "fqdn"); - - xml_node_create(ctx->xml, c, NULL, "SubscriptionParameters"); - - cred = xml_node_create(ctx->xml, c, NULL, "Credential"); - add_creation_date(ctx, cred); - if (imsi) { - xml_node_t *sim; - const char *type = "18"; /* default to EAP-SIM */ - - sim = xml_node_create(ctx->xml, cred, NULL, "SIM"); - add_text_node(ctx, sim, "IMSI", imsi); - if (ctx->eap_method && os_strcmp(ctx->eap_method, "AKA") == 0) - type = "23"; - else if (ctx->eap_method && - os_strcmp(ctx->eap_method, "AKA'") == 0) - type = "50"; - add_text_node(ctx, sim, "EAPType", type); - } else if (cert) { - xml_node_t *dc; - dc = xml_node_create(ctx->xml, cred, NULL, - "DigitalCertificate"); - add_text_node(ctx, dc, "CertificateType", "x509v3"); - add_text_node(ctx, dc, "CertSHA256Fingerprint", cert); - } else { - userpw = build_username_password(ctx, cred, user, pw); - add_text_node(ctx, userpw, "MachineManaged", - machine_managed ? "TRUE" : "FALSE"); - eap = xml_node_create(ctx->xml, userpw, NULL, "EAPMethod"); - add_text_node(ctx, eap, "EAPType", "21"); - add_text_node(ctx, eap, "InnerMethod", "MS-CHAP-V2"); - } - add_text_node(ctx, cred, "Realm", realm); - - return pps; -} - - -static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, - const char *session_id, - const char *user, - const char *realm, - int add_est_user) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *enroll, *exec_node; - char *val; - char password[11]; - char *b64; - - if (add_est_user && new_password(password, sizeof(password)) < 0) - return NULL; - - spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", - NULL); - if (spp_node == NULL) - return NULL; - - exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); - - enroll = xml_node_create(ctx->xml, exec_node, ns, "getCertificate"); - xml_node_add_attr(ctx->xml, enroll, NULL, "enrollmentProtocol", "EST"); - - val = db_get_osu_config_val(ctx, realm, "est_url"); - xml_node_create_text(ctx->xml, enroll, ns, "enrollmentServerURI", - val ? val : ""); - os_free(val); - - if (!add_est_user) - return spp_node; - - xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user); - - b64 = base64_encode(password, strlen(password), NULL); - if (b64 == NULL) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - xml_node_create_text(ctx->xml, enroll, ns, "estPassword", b64); - free(b64); - - db_update_session_password(ctx, user, realm, session_id, password); - - return spp_node; -} - - -static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx, - const char *session_id, - int enrollment_done) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node = NULL; - xml_node_t *pps, *tnds; - char buf[400]; - char *str; - char *user, *realm, *pw, *type, *mm, *test; - const char *status; - int cert = 0; - int machine_managed = 0; - char *fingerprint; - - user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); - realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); - pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); - - if (!user || !realm || !pw) { - debug_print(ctx, 1, "Could not find session info from DB for " - "the new subscription"); - free(user); - free(realm); - free(pw); - return NULL; - } - - mm = db_get_session_val(ctx, NULL, NULL, session_id, "machine_managed"); - if (mm && atoi(mm)) - machine_managed = 1; - free(mm); - - type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); - if (type && strcmp(type, "cert") == 0) - cert = 1; - free(type); - - if (cert && !enrollment_done) { - xml_node_t *ret; - hs20_eventlog(ctx, user, realm, session_id, - "request client certificate enrollment", NULL); - ret = spp_exec_get_certificate(ctx, session_id, user, realm, 1); - free(user); - free(realm); - free(pw); - return ret; - } - - if (!cert && strlen(pw) == 0) { - machine_managed = 1; - free(pw); - pw = malloc(11); - if (pw == NULL || new_password(pw, 11) < 0) { - free(user); - free(realm); - free(pw); - return NULL; - } - } - - status = "Provisioning complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); - test = db_get_session_val(ctx, NULL, NULL, session_id, "test"); - if (test) - debug_print(ctx, 1, "TEST: Requested special behavior: %s", - test); - pps = build_pps(ctx, user, realm, pw, - fingerprint ? fingerprint : NULL, machine_managed, - test, NULL, NULL, NULL, NULL); - free(fingerprint); - free(test); - if (!pps) { - xml_node_free(ctx->xml, spp_node); - free(user); - free(realm); - free(pw); - return NULL; - } - - debug_print(ctx, 1, "Request DB subscription registration on success " - "notification"); - if (machine_managed) { - db_update_session_password(ctx, user, realm, session_id, pw); - db_update_session_machine_managed(ctx, user, realm, session_id, - machine_managed); - } - db_add_session_pps(ctx, user, realm, session_id, pps); - - hs20_eventlog_node(ctx, user, realm, session_id, - "new subscription", pps); - free(user); - free(pw); - - tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); - xml_node_free(ctx->xml, pps); - if (!tnds) { - xml_node_free(ctx->xml, spp_node); - free(realm); - return NULL; - } - - str = xml_node_to_str(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (str == NULL) { - xml_node_free(ctx->xml, spp_node); - free(realm); - return NULL; - } - - node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); - free(str); - snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); - free(realm); - xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); - xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); - - return spp_node; -} - - -static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx, - const char *user, - const char *realm, - const char *session_id) -{ - xml_namespace_t *ns; - xml_node_t *spp_node; - xml_node_t *cred; - char buf[400]; - char *status; - char *free_account, *pw; - - free_account = db_get_osu_config_val(ctx, realm, "free_account"); - if (free_account == NULL) - return NULL; - pw = db_get_val(ctx, free_account, realm, "password", 0); - if (pw == NULL) { - free(free_account); - return NULL; - } - - cred = build_credential_pw(ctx, free_account, realm, pw, 1); - free(free_account); - free(pw); - if (!cred) { - xml_node_free(ctx->xml, cred); - return NULL; - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "free/public remediation", cred); - xml_node_free(ctx->xml, cred); - - return spp_node; -} - - -static xml_node_t * hs20_user_input_complete(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - char *val; - enum hs20_session_operation oper; - - val = db_get_session_val(ctx, user, realm, session_id, "operation"); - if (val == NULL) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - return NULL; - } - oper = atoi(val); - free(val); - - if (oper == USER_REMEDIATION) { - return hs20_user_input_remediation(ctx, user, realm, dmacc, - session_id); - } - - if (oper == FREE_REMEDIATION) { - return hs20_user_input_free_remediation(ctx, user, realm, - session_id); - } - - if (oper == SUBSCRIPTION_REGISTRATION) { - return hs20_user_input_registration(ctx, session_id, 0); - } - - debug_print(ctx, 1, "User session %s not in state for user input " - "completion", session_id); - return NULL; -} - - -static xml_node_t * hs20_cert_reenroll_complete(struct hs20_svc *ctx, - const char *session_id) -{ - char *user, *realm, *cert; - char *status; - xml_namespace_t *ns; - xml_node_t *spp_node, *cred; - char buf[400]; - - user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); - realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); - cert = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); - if (!user || !realm || !cert) { - debug_print(ctx, 1, - "Could not find session info from DB for certificate reenrollment"); - free(user); - free(realm); - free(cert); - return NULL; - } - - cred = build_credential_cert(ctx, user, realm, cert); - if (!cred) { - debug_print(ctx, 1, "Could not build credential"); - free(user); - free(realm); - free(cert); - return NULL; - } - - status = "Remediation complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) { - debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); - free(user); - free(realm); - free(cert); - xml_node_free(ctx->xml, cred); - return NULL; - } - - snprintf(buf, sizeof(buf), - "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", - realm); - - if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { - debug_print(ctx, 1, "Could not add update node"); - xml_node_free(ctx->xml, spp_node); - free(user); - free(realm); - free(cert); - return NULL; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "certificate reenrollment", cred); - xml_node_free(ctx->xml, cred); - - free(user); - free(realm); - free(cert); - return spp_node; -} - - -static xml_node_t * hs20_cert_enroll_completed(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - char *val; - enum hs20_session_operation oper; - - val = db_get_session_val(ctx, NULL, NULL, session_id, "operation"); - if (val == NULL) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - return NULL; - } - oper = atoi(val); - free(val); - - if (oper == SUBSCRIPTION_REGISTRATION) - return hs20_user_input_registration(ctx, session_id, 1); - if (oper == CERT_REENROLL) - return hs20_cert_reenroll_complete(ctx, session_id); - - debug_print(ctx, 1, "User session %s not in state for certificate " - "enrollment completion", session_id); - return NULL; -} - - -static xml_node_t * hs20_cert_enroll_failed(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - char *val; - enum hs20_session_operation oper; - xml_node_t *spp_node, *node; - char *status; - xml_namespace_t *ns; - - val = db_get_session_val(ctx, user, realm, session_id, "operation"); - if (val == NULL) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - return NULL; - } - oper = atoi(val); - free(val); - - if (oper != SUBSCRIPTION_REGISTRATION) { - debug_print(ctx, 1, "User session %s not in state for " - "enrollment failure", session_id); - return NULL; - } - - status = "Error occurred"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (spp_node == NULL) - return NULL; - node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); - xml_node_add_attr(ctx->xml, node, NULL, "errorCode", - "Credentials cannot be provisioned at this time"); - db_remove_session(ctx, user, realm, session_id); - - return spp_node; -} - - -static xml_node_t * hs20_sim_provisioning(struct hs20_svc *ctx, - const char *user, - const char *realm, int dmacc, - const char *session_id) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node = NULL; - xml_node_t *pps, *tnds; - char buf[400]; - char *str; - const char *status; - char dmacc_username[32]; - char dmacc_password[32]; - char *policy; - xml_node_t *policy_node = NULL; - - if (!ctx->imsi) { - debug_print(ctx, 1, "IMSI not available for SIM provisioning"); - return NULL; - } - - if (new_password(dmacc_username, sizeof(dmacc_username)) < 0 || - new_password(dmacc_password, sizeof(dmacc_password)) < 0) { - debug_print(ctx, 1, - "Failed to generate DMAcc username/password"); - return NULL; - } - - status = "Provisioning complete, request sppUpdateResponse"; - spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, - NULL); - if (!spp_node) - return NULL; - - policy = db_get_osu_config_val(ctx, realm, "sim_policy"); - if (policy) { - policy_node = read_policy_file(ctx, policy); - os_free(policy); - if (!policy_node) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - update_policy_update_uri(ctx, realm, policy_node); - node = get_node_uri(ctx->xml, policy_node, - "Policy/PolicyUpdate"); - if (node) - build_username_password(ctx, node, dmacc_username, - dmacc_password); - } - - pps = build_pps(ctx, NULL, realm, NULL, NULL, 0, NULL, ctx->imsi, - dmacc_username, dmacc_password, policy_node); - if (!pps) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - debug_print(ctx, 1, - "Request DB subscription registration on success notification"); - if (!user || !user[0]) - user = ctx->imsi; - db_add_session(ctx, user, realm, session_id, NULL, NULL, - SUBSCRIPTION_REGISTRATION, NULL); - db_add_session_dmacc(ctx, session_id, dmacc_username, dmacc_password); - if (ctx->eap_method) - db_add_session_eap_method(ctx, session_id, ctx->eap_method); - if (ctx->id_hash) - db_add_session_id_hash(ctx, session_id, ctx->id_hash); - db_add_session_pps(ctx, user, realm, session_id, pps); - - hs20_eventlog_node(ctx, user, realm, session_id, - "new subscription", pps); - - tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); - xml_node_free(ctx->xml, pps); - if (!tnds) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - str = xml_node_to_str(ctx->xml, tnds); - xml_node_free(ctx->xml, tnds); - if (!str) { - xml_node_free(ctx->xml, spp_node); - return NULL; - } - - node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); - free(str); - snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); - xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); - xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); - - return spp_node; -} - - -static xml_node_t * hs20_spp_post_dev_data(struct hs20_svc *ctx, - xml_node_t *node, - const char *user, - const char *realm, - const char *session_id, - int dmacc) -{ - const char *req_reason; - char *redirect_uri = NULL; - char *req_reason_buf = NULL; - char str[200]; - xml_node_t *ret = NULL, *devinfo = NULL, *devdetail = NULL; - xml_node_t *mo, *macaddr; - char *version; - int valid; - char *supp, *pos; - char *err; - u8 wifi_mac_addr[ETH_ALEN]; - - version = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, - "sppVersion"); - if (version == NULL || strstr(version, "1.0") == NULL) { - ret = build_post_dev_data_response( - ctx, NULL, session_id, "Error occurred", - "SPP version not supported"); - hs20_eventlog_node(ctx, user, realm, session_id, - "Unsupported sppVersion", ret); - xml_node_get_attr_value_free(ctx->xml, version); - return ret; - } - xml_node_get_attr_value_free(ctx->xml, version); - - mo = get_node(ctx->xml, node, "supportedMOList"); - if (mo == NULL) { - ret = build_post_dev_data_response( - ctx, NULL, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, - "No supportedMOList element", ret); - return ret; - } - supp = xml_node_get_text(ctx->xml, mo); - for (pos = supp; pos && *pos; pos++) - *pos = tolower(*pos); - if (supp == NULL || - strstr(supp, URN_OMA_DM_DEVINFO) == NULL || - strstr(supp, URN_OMA_DM_DEVDETAIL) == NULL || - strstr(supp, URN_HS20_PPS) == NULL) { - xml_node_get_text_free(ctx->xml, supp); - ret = build_post_dev_data_response( - ctx, NULL, session_id, "Error occurred", - "One or more mandatory MOs not supported"); - hs20_eventlog_node(ctx, user, realm, session_id, - "Unsupported MOs", ret); - return ret; - } - xml_node_get_text_free(ctx->xml, supp); - - req_reason_buf = xml_node_get_attr_value(ctx->xml, node, - "requestReason"); - if (req_reason_buf == NULL) { - debug_print(ctx, 1, "No requestReason attribute"); - return NULL; - } - req_reason = req_reason_buf; - - redirect_uri = xml_node_get_attr_value(ctx->xml, node, "redirectURI"); - - debug_print(ctx, 1, "requestReason: %s sessionID: %s redirectURI: %s", - req_reason, session_id, redirect_uri); - snprintf(str, sizeof(str), "sppPostDevData: requestReason=%s", - req_reason); - hs20_eventlog(ctx, user, realm, session_id, str, NULL); - - devinfo = spp_get_mo(ctx, node, URN_OMA_DM_DEVINFO, &valid, &err); - if (devinfo == NULL) { - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, - "No DevInfo moContainer in sppPostDevData", - ret); - os_free(err); - goto out; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "Received DevInfo MO", devinfo); - if (valid == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "OMA-DM DDF DTD validation errors in DevInfo MO", - err); - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - os_free(err); - goto out; - } - os_free(err); - if (user) - db_update_mo(ctx, user, realm, "devinfo", devinfo); - - devdetail = spp_get_mo(ctx, node, URN_OMA_DM_DEVDETAIL, &valid, &err); - if (devdetail == NULL) { - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, - "No DevDetail moContainer in sppPostDevData", - ret); - os_free(err); - goto out; - } - - hs20_eventlog_node(ctx, user, realm, session_id, - "Received DevDetail MO", devdetail); - if (valid == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "OMA-DM DDF DTD validation errors " - "in DevDetail MO", err); - ret = build_post_dev_data_response(ctx, NULL, session_id, - "Error occurred", "Other"); - os_free(err); - goto out; - } - os_free(err); - - os_memset(wifi_mac_addr, 0, ETH_ALEN); - macaddr = get_node(ctx->xml, devdetail, - "Ext/org.wi-fi/Wi-Fi/Wi-FiMACAddress"); - if (macaddr) { - char *addr, buf[50]; - - addr = xml_node_get_text(ctx->xml, macaddr); - if (addr && hwaddr_compact_aton(addr, wifi_mac_addr) == 0) { - snprintf(buf, sizeof(buf), "DevDetail MAC address: " - MACSTR, MAC2STR(wifi_mac_addr)); - hs20_eventlog(ctx, user, realm, session_id, buf, NULL); - xml_node_get_text_free(ctx->xml, addr); - } else { - hs20_eventlog(ctx, user, realm, session_id, - "Could not extract MAC address from DevDetail", - NULL); - } - } else { - hs20_eventlog(ctx, user, realm, session_id, - "No MAC address in DevDetail", NULL); - } - - if (user) - db_update_mo(ctx, user, realm, "devdetail", devdetail); - - if (user) - mo = spp_get_mo(ctx, node, URN_HS20_PPS, &valid, &err); - else { - mo = NULL; - err = NULL; - } - if (user && mo) { - hs20_eventlog_node(ctx, user, realm, session_id, - "Received PPS MO", mo); - if (valid == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "OMA-DM DDF DTD validation errors " - "in PPS MO", err); - xml_node_get_attr_value_free(ctx->xml, redirect_uri); - os_free(err); - return build_post_dev_data_response( - ctx, NULL, session_id, - "Error occurred", "Other"); - } - db_update_mo(ctx, user, realm, "pps", mo); - db_update_val(ctx, user, realm, "fetch_pps", "0", dmacc); - xml_node_free(ctx->xml, mo); - } - os_free(err); - - if (user && !mo) { - char *fetch; - int fetch_pps; - - fetch = db_get_val(ctx, user, realm, "fetch_pps", dmacc); - fetch_pps = fetch ? atoi(fetch) : 0; - free(fetch); - - if (fetch_pps) { - enum hs20_session_operation oper; - if (strcasecmp(req_reason, "Subscription remediation") - == 0) - oper = CONTINUE_SUBSCRIPTION_REMEDIATION; - else if (strcasecmp(req_reason, "Policy update") == 0) - oper = CONTINUE_POLICY_UPDATE; - else - oper = NO_OPERATION; - if (db_add_session(ctx, user, realm, session_id, NULL, - NULL, oper, NULL) < 0) - goto out; - - ret = spp_exec_upload_mo(ctx, session_id, - URN_HS20_PPS); - hs20_eventlog_node(ctx, user, realm, session_id, - "request PPS MO upload", - ret); - goto out; - } - } - - if (user && strcasecmp(req_reason, "MO upload") == 0) { - char *val = db_get_session_val(ctx, user, realm, session_id, - "operation"); - enum hs20_session_operation oper; - if (!val) { - debug_print(ctx, 1, "No session %s found to continue", - session_id); - goto out; - } - oper = atoi(val); - free(val); - if (oper == CONTINUE_SUBSCRIPTION_REMEDIATION) - req_reason = "Subscription remediation"; - else if (oper == CONTINUE_POLICY_UPDATE) - req_reason = "Policy update"; - else { - debug_print(ctx, 1, - "No pending operation in session %s", - session_id); - goto out; - } - } - - if (strcasecmp(req_reason, "Subscription registration") == 0) { - ret = hs20_subscription_registration(ctx, realm, session_id, - redirect_uri, - wifi_mac_addr); - hs20_eventlog_node(ctx, user, realm, session_id, - "subscription registration response", - ret); - goto out; - } - if (user && strcasecmp(req_reason, "Subscription remediation") == 0) { - ret = hs20_subscription_remediation(ctx, user, realm, - session_id, dmacc, - redirect_uri); - hs20_eventlog_node(ctx, user, realm, session_id, - "subscription remediation response", - ret); - goto out; - } - if (user && strcasecmp(req_reason, "Policy update") == 0) { - ret = hs20_policy_update(ctx, user, realm, session_id, dmacc); - hs20_eventlog_node(ctx, user, realm, session_id, - "policy update response", - ret); - goto out; - } - - if (strcasecmp(req_reason, "User input completed") == 0) { - db_add_session_devinfo(ctx, session_id, devinfo); - db_add_session_devdetail(ctx, session_id, devdetail); - ret = hs20_user_input_complete(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "user input completed response", ret); - goto out; - } - - if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) { - ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "certificate enrollment response", ret); - goto out; - } - - if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) { - ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "certificate enrollment failed response", - ret); - goto out; - } - - if (strcasecmp(req_reason, "Subscription provisioning") == 0) { - ret = hs20_sim_provisioning(ctx, user, realm, dmacc, - session_id); - hs20_eventlog_node(ctx, user, realm, session_id, - "subscription provisioning response", - ret); - goto out; - } - - debug_print(ctx, 1, "Unsupported requestReason '%s' user '%s'", - req_reason, user); -out: - xml_node_get_attr_value_free(ctx->xml, req_reason_buf); - xml_node_get_attr_value_free(ctx->xml, redirect_uri); - if (devinfo) - xml_node_free(ctx->xml, devinfo); - if (devdetail) - xml_node_free(ctx->xml, devdetail); - return ret; -} - - -static xml_node_t * build_spp_exchange_complete(struct hs20_svc *ctx, - const char *session_id, - const char *status, - const char *error_code) -{ - xml_namespace_t *ns; - xml_node_t *spp_node, *node; - - spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, - "sppExchangeComplete"); - - - xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); - xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); - xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); - - if (error_code) { - node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); - xml_node_add_attr(ctx->xml, node, NULL, "errorCode", - error_code); - } - - return spp_node; -} - - -static int add_subscription(struct hs20_svc *ctx, const char *session_id) -{ - char *user, *realm, *pw, *pw_mm, *pps, *str; - char *osu_user, *osu_password, *eap_method; - char *policy = NULL; - char *sql; - int ret = -1; - char *free_account; - int free_acc; - char *type; - int cert = 0; - char *cert_pem, *fingerprint; - const char *method; - - user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); - realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); - pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); - pw_mm = db_get_session_val(ctx, NULL, NULL, session_id, - "machine_managed"); - pps = db_get_session_val(ctx, NULL, NULL, session_id, "pps"); - cert_pem = db_get_session_val(ctx, NULL, NULL, session_id, "cert_pem"); - fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); - type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); - if (type && strcmp(type, "cert") == 0) - cert = 1; - free(type); - osu_user = db_get_session_val(ctx, NULL, NULL, session_id, "osu_user"); - osu_password = db_get_session_val(ctx, NULL, NULL, session_id, - "osu_password"); - eap_method = db_get_session_val(ctx, NULL, NULL, session_id, - "eap_method"); - - if (!user || !realm || !pw) { - debug_print(ctx, 1, "Could not find session info from DB for " - "the new subscription"); - goto out; - } - - free_account = db_get_osu_config_val(ctx, realm, "free_account"); - free_acc = free_account && strcmp(free_account, user) == 0; - free(free_account); - - policy = db_get_osu_config_val(ctx, realm, "sim_policy"); - - debug_print(ctx, 1, - "New subscription: user='%s' realm='%s' free_acc=%d", - user, realm, free_acc); - debug_print(ctx, 1, "New subscription: pps='%s'", pps); - - sql = sqlite3_mprintf("UPDATE eventlog SET user=%Q, realm=%Q WHERE " - "sessionid=%Q AND (user='' OR user IS NULL)", - user, realm, session_id); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to update eventlog in " - "sqlite database: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); - } - - if (free_acc) { - hs20_eventlog(ctx, user, realm, session_id, - "completed shared free account registration", - NULL); - ret = 0; - goto out; - } - - str = db_get_session_val(ctx, NULL, NULL, session_id, "mac_addr"); - - if (eap_method && eap_method[0]) - method = eap_method; - else - method = cert ? "TLS" : "TTLS-MSCHAPV2"; - sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2,methods,cert,cert_pem,machine_managed,mac_addr,osu_user,osu_password,policy) VALUES (%Q,%Q,%d,%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", - user, realm, cert ? 0 : 1, - method, - fingerprint ? fingerprint : "", - cert_pem ? cert_pem : "", - pw_mm && atoi(pw_mm) ? 1 : 0, - str ? str : "", - osu_user ? osu_user : "", - osu_password ? osu_password : "", - policy ? policy : ""); - free(str); - if (sql == NULL) - goto out; - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { - debug_print(ctx, 1, "Failed to add user in sqlite database: %s", - sqlite3_errmsg(ctx->db)); - sqlite3_free(sql); - goto out; - } - sqlite3_free(sql); - - if (cert) - ret = 0; - else - ret = update_password(ctx, user, realm, pw, 0); - if (ret < 0) { - sql = sqlite3_mprintf("DELETE FROM users WHERE identity=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", - user, realm); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - sqlite3_exec(ctx->db, sql, NULL, NULL, NULL); - sqlite3_free(sql); - } - } - - if (pps) - db_update_mo_str(ctx, user, realm, "pps", pps); - - str = db_get_session_val(ctx, NULL, NULL, session_id, "devinfo"); - if (str) { - db_update_mo_str(ctx, user, realm, "devinfo", str); - free(str); - } - - str = db_get_session_val(ctx, NULL, NULL, session_id, "devdetail"); - if (str) { - db_update_mo_str(ctx, user, realm, "devdetail", str); - free(str); - } - - if (cert && user) { - const char *serialnum; - - str = db_get_session_val(ctx, NULL, NULL, session_id, - "mac_addr"); - - if (os_strncmp(user, "cert-", 5) == 0) - serialnum = user + 5; - else - serialnum = ""; - sql = sqlite3_mprintf("INSERT OR REPLACE INTO cert_enroll (mac_addr,user,realm,serialnum) VALUES(%Q,%Q,%Q,%Q)", - str ? str : "", user, realm ? realm : "", - serialnum); - free(str); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != - SQLITE_OK) { - debug_print(ctx, 1, - "Failed to add cert_enroll entry into sqlite database: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); - } - } - - str = db_get_session_val(ctx, NULL, NULL, session_id, - "mobile_identifier_hash"); - if (str) { - sql = sqlite3_mprintf("DELETE FROM sim_provisioning WHERE mobile_identifier_hash=%Q", - str); - if (sql) { - debug_print(ctx, 1, "DB: %s", sql); - if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != - SQLITE_OK) { - debug_print(ctx, 1, - "Failed to delete pending sim_provisioning entry: %s", - sqlite3_errmsg(ctx->db)); - } - sqlite3_free(sql); - } - os_free(str); - } - - if (ret == 0) { - hs20_eventlog(ctx, user, realm, session_id, - "completed subscription registration", NULL); - } - -out: - free(user); - free(realm); - free(pw); - free(pw_mm); - free(pps); - free(cert_pem); - free(fingerprint); - free(osu_user); - free(osu_password); - free(eap_method); - os_free(policy); - return ret; -} - - -static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx, - xml_node_t *node, - const char *user, - const char *realm, - const char *session_id, - int dmacc) -{ - char *status; - xml_node_t *ret; - char *val; - enum hs20_session_operation oper; - - status = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, - "sppStatus"); - if (status == NULL) { - debug_print(ctx, 1, "No sppStatus attribute"); - return NULL; - } - - debug_print(ctx, 1, "sppUpdateResponse: sppStatus: %s sessionID: %s", - status, session_id); - - val = db_get_session_val(ctx, NULL, NULL, session_id, "operation"); - if (!val) { - debug_print(ctx, 1, - "No session active for sessionID: %s", - session_id); - oper = NO_OPERATION; - } else - oper = atoi(val); - - if (strcasecmp(status, "OK") == 0) { - char *new_pw = NULL; - - xml_node_get_attr_value_free(ctx->xml, status); - - if (oper == USER_REMEDIATION) { - new_pw = db_get_session_val(ctx, user, realm, - session_id, "password"); - if (new_pw == NULL || strlen(new_pw) == 0) { - free(new_pw); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, "No password " - "had been assigned for " - "session", ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - oper = UPDATE_PASSWORD; - } - if (oper == UPDATE_PASSWORD) { - if (!new_pw) { - new_pw = db_get_session_val(ctx, user, realm, - session_id, - "password"); - if (!new_pw) { - db_remove_session(ctx, user, realm, - session_id); - return NULL; - } - } - debug_print(ctx, 1, "Update user '%s' password in DB", - user); - if (update_password(ctx, user, realm, new_pw, dmacc) < - 0) { - debug_print(ctx, 1, "Failed to update user " - "'%s' password in DB", user); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, "Failed to " - "update database", ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - hs20_eventlog(ctx, user, realm, - session_id, "Updated user password " - "in database", NULL); - } - if (oper == CLEAR_REMEDIATION) { - debug_print(ctx, 1, - "Clear remediation requirement for user '%s' in DB", - user); - if (clear_remediation(ctx, user, realm, dmacc) < 0) { - debug_print(ctx, 1, - "Failed to clear remediation requirement for user '%s' in DB", - user); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, - "Failed to update database", - ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - hs20_eventlog(ctx, user, realm, - session_id, - "Cleared remediation requirement in database", - NULL); - } - if (oper == SUBSCRIPTION_REGISTRATION) { - if (add_subscription(ctx, session_id) < 0) { - debug_print(ctx, 1, "Failed to add " - "subscription into DB"); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, "Failed to " - "update database", ret); - db_remove_session(ctx, user, realm, session_id); - return ret; - } - } - if (oper == POLICY_REMEDIATION || oper == POLICY_UPDATE) { - char *val; - val = db_get_val(ctx, user, realm, "remediation", - dmacc); - if (val && strcmp(val, "policy") == 0) - db_update_val(ctx, user, realm, "remediation", - "", dmacc); - free(val); - } - if (oper == POLICY_UPDATE) - db_update_val(ctx, user, realm, "polupd_done", "1", - dmacc); - if (oper == CERT_REENROLL) { - char *new_user; - char event[200]; - - new_user = db_get_session_val(ctx, NULL, NULL, - session_id, "user"); - if (!new_user) { - debug_print(ctx, 1, - "Failed to find new user name (cert-serialnum)"); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, - "Failed to find new user name (cert reenroll)", - ret); - db_remove_session(ctx, NULL, NULL, session_id); - return ret; - } - - debug_print(ctx, 1, - "Update certificate user entry to use the new serial number (old=%s new=%s)", - user, new_user); - os_snprintf(event, sizeof(event), "renamed user to: %s", - new_user); - hs20_eventlog(ctx, user, realm, session_id, event, - NULL); - - if (db_update_val(ctx, user, realm, "identity", - new_user, 0) < 0 || - db_update_val(ctx, new_user, realm, "remediation", - "", 0) < 0) { - debug_print(ctx, 1, - "Failed to update user name (cert-serialnum)"); - ret = build_spp_exchange_complete( - ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, - session_id, - "Failed to update user name (cert reenroll)", - ret); - db_remove_session(ctx, NULL, NULL, session_id); - os_free(new_user); - return ret; - } - - os_free(new_user); - } - ret = build_spp_exchange_complete( - ctx, session_id, - "Exchange complete, release TLS connection", NULL); - hs20_eventlog_node(ctx, user, realm, session_id, - "Exchange completed", ret); - db_remove_session(ctx, NULL, NULL, session_id); - return ret; - } - - ret = build_spp_exchange_complete(ctx, session_id, "Error occurred", - "Other"); - hs20_eventlog_node(ctx, user, realm, session_id, "Error occurred", ret); - db_remove_session(ctx, user, realm, session_id); - xml_node_get_attr_value_free(ctx->xml, status); - return ret; -} - - -#define SPP_SESSION_ID_LEN 16 - -static char * gen_spp_session_id(void) -{ - FILE *f; - int i; - char *session; - - session = os_malloc(SPP_SESSION_ID_LEN * 2 + 1); - if (session == NULL) - return NULL; - - f = fopen("/dev/urandom", "r"); - if (f == NULL) { - os_free(session); - return NULL; - } - for (i = 0; i < SPP_SESSION_ID_LEN; i++) - os_snprintf(session + i * 2, 3, "%02x", fgetc(f)); - - fclose(f); - return session; -} - -xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node, - const char *auth_user, - const char *auth_realm, int dmacc) -{ - xml_node_t *ret = NULL; - char *session_id; - const char *op_name; - char *xml_err; - char fname[200]; - - debug_dump_node(ctx, "received request", node); - - if (!dmacc && auth_user && auth_realm) { - char *real; - real = db_get_val(ctx, auth_user, auth_realm, "identity", 0); - if (!real) { - real = db_get_val(ctx, auth_user, auth_realm, - "identity", 1); - if (real) - dmacc = 1; - } - os_free(real); - } - - snprintf(fname, sizeof(fname), "%s/spp/spp.xsd", ctx->root_dir); - if (xml_validate(ctx->xml, node, fname, &xml_err) < 0) { - /* - * We may not be able to extract the sessionID from invalid - * input, but well, we can try. - */ - session_id = xml_node_get_attr_value_ns(ctx->xml, node, - SPP_NS_URI, - "sessionID"); - debug_print(ctx, 1, - "SPP message failed validation, xsd file: %s xml-error: %s", - fname, xml_err); - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "SPP message failed validation", node); - hs20_eventlog(ctx, auth_user, auth_realm, session_id, - "Validation errors", xml_err); - os_free(xml_err); - xml_node_get_attr_value_free(ctx->xml, session_id); - /* TODO: what to return here? */ - ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "SppValidationError"); - return ret; - } - - session_id = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, - "sessionID"); - if (session_id) { - char *tmp; - debug_print(ctx, 1, "Received sessionID %s", session_id); - tmp = os_strdup(session_id); - xml_node_get_attr_value_free(ctx->xml, session_id); - if (tmp == NULL) - return NULL; - session_id = tmp; - } else { - session_id = gen_spp_session_id(); - if (session_id == NULL) { - debug_print(ctx, 1, "Failed to generate sessionID"); - return NULL; - } - debug_print(ctx, 1, "Generated sessionID %s", session_id); - } - - op_name = xml_node_get_localname(ctx->xml, node); - if (op_name == NULL) { - debug_print(ctx, 1, "Could not get op_name"); - return NULL; - } - - if (strcmp(op_name, "sppPostDevData") == 0) { - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "sppPostDevData received and validated", - node); - ret = hs20_spp_post_dev_data(ctx, node, auth_user, auth_realm, - session_id, dmacc); - } else if (strcmp(op_name, "sppUpdateResponse") == 0) { - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "sppUpdateResponse received and validated", - node); - ret = hs20_spp_update_response(ctx, node, auth_user, - auth_realm, session_id, dmacc); - } else { - hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, - "Unsupported SPP message received and " - "validated", node); - debug_print(ctx, 1, "Unsupported operation '%s'", op_name); - /* TODO: what to return here? */ - ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "SppUnknownCommandError"); - } - os_free(session_id); - - if (ret == NULL) { - /* TODO: what to return here? */ - ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, - "SppInternalError"); - } - - return ret; -} - - -int hs20_spp_server_init(struct hs20_svc *ctx) -{ - char fname[200]; - ctx->db = NULL; - snprintf(fname, sizeof(fname), "%s/AS/DB/eap_user.db", ctx->root_dir); - if (sqlite3_open(fname, &ctx->db)) { - printf("Failed to open sqlite database: %s\n", - sqlite3_errmsg(ctx->db)); - sqlite3_close(ctx->db); - return -1; - } - - return 0; -} - - -void hs20_spp_server_deinit(struct hs20_svc *ctx) -{ - sqlite3_close(ctx->db); - ctx->db = NULL; -} diff --git a/contrib/wpa/hs20/server/spp_server.h b/contrib/wpa/hs20/server/spp_server.h deleted file mode 100644 index 421974c607b8..000000000000 --- a/contrib/wpa/hs20/server/spp_server.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Hotspot 2.0 SPP server - * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#ifndef SPP_SERVER_H -#define SPP_SERVER_H - -struct hs20_svc { - const void *ctx; - struct xml_node_ctx *xml; - char *root_dir; - FILE *debug_log; - sqlite3 *db; - const char *addr; - const char *test; - const char *imsi; - const char *eap_method; - const char *id_hash; -}; - - -void debug_print(struct hs20_svc *ctx, int print, const char *fmt, ...) - __attribute__ ((format (printf, 3, 4))); -void debug_dump_node(struct hs20_svc *ctx, const char *title, xml_node_t *node); - -xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node, - const char *auth_user, - const char *auth_realm, int dmacc); -int hs20_spp_server_init(struct hs20_svc *ctx); -void hs20_spp_server_deinit(struct hs20_svc *ctx); - -#endif /* SPP_SERVER_H */ diff --git a/contrib/wpa/hs20/server/sql-example.txt b/contrib/wpa/hs20/server/sql-example.txt deleted file mode 100644 index 20dcf2f5c688..000000000000 --- a/contrib/wpa/hs20/server/sql-example.txt +++ /dev/null @@ -1,17 +0,0 @@ -INSERT INTO osu_config(realm,field,value) VALUES('example.com','fqdn','example.com'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','friendly_name','Example Operator'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','spp_http_auth_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/spp-root-ca.der'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_url','https://osu-server.osu.example.com/hs20/files/aaa-root-ca.der'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','aaa_trust_root_cert_fingerprint','5b393a9246865569485c2605c3304e48212b449367858299beba9384c4cf4647'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_account','free'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','policy_url','https://subscription-server.osu.example.com/hs20/spp.php?realm=example.com'); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','remediation_url','https://subscription-server.osu.example.com/hs20/remediation.php?session_id='); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','free_remediation_url','https://subscription-server.osu.example.com/hs20/free-remediation.php?session_id='); -INSERT INTO osu_config(realm,field,value) VALUES('example.com','signup_url','https://subscription-server.osu.example.com/hs20/signup.php?session_id='); - - -INSERT INTO users(identity,realm,methods,password,phase2,shared) VALUES('free','example.com','TTLS-MSCHAPV2','free',1,1); - -INSERT INTO wildcards(identity,methods) VALUES('','TTLS,TLS'); diff --git a/contrib/wpa/hs20/server/sql.txt b/contrib/wpa/hs20/server/sql.txt deleted file mode 100644 index 2cc6edea4063..000000000000 --- a/contrib/wpa/hs20/server/sql.txt +++ /dev/null @@ -1,108 +0,0 @@ -CREATE TABLE eventlog( - user TEXT, - realm TEXT, - sessionid TEXT COLLATE NOCASE, - timestamp TEXT, - notes TEXT, - dump TEXT, - addr TEXT -); - -CREATE TABLE sessions( - timestamp TEXT, - id TEXT COLLATE NOCASE, - user TEXT, - realm TEXT, - password TEXT, - machine_managed BOOLEAN, - operation INTEGER, - type TEXT, - pps TEXT, - redirect_uri TEXT, - devinfo TEXT, - devdetail TEXT, - cert TEXT, - cert_pem TEXT, - mac_addr TEXT, - osu_user TEXT, - osu_password TEXT, - eap_method TEXT, - mobile_identifier_hash TEXT, - test TEXT -); - -CREATE index sessions_id_index ON sessions(id); - -CREATE TABLE osu_config( - realm TEXT, - field TEXT, - value TEXT -); - -CREATE TABLE users( - identity TEXT PRIMARY KEY, - methods TEXT, - password TEXT, - machine_managed BOOLEAN, - remediation TEXT, - phase2 INTEGER, - realm TEXT, - policy TEXT, - devinfo TEXT, - devdetail TEXT, - pps TEXT, - fetch_pps INTEGER, - osu_user TEXT, - osu_password TEXT, - shared INTEGER, - cert TEXT, - cert_pem TEXT, - t_c_timestamp INTEGER, - mac_addr TEXT, - last_msk TEXT, - polupd_done TEXT, - subrem TEXT -); - -CREATE TABLE wildcards( - identity TEXT PRIMARY KEY, - methods TEXT -); - -CREATE TABLE authlog( - timestamp TEXT, - session TEXT, - nas_ip TEXT, - username TEXT, - note TEXT -); - -CREATE TABLE pending_tc( - mac_addr TEXT PRIMARY KEY, - identity TEXT -); - -CREATE TABLE current_sessions( - mac_addr TEXT PRIMARY KEY, - identity TEXT, - start_time TEXT, - nas TEXT, - hs20_t_c_filtering BOOLEAN, - waiting_coa_ack BOOLEAN, - coa_ack_received BOOLEAN -); - -CREATE TABLE cert_enroll( - mac_addr TEXT PRIMARY KEY, - user TEXT, - realm TEXT, - serialnum TEXT -); - -CREATE TABLE sim_provisioning( - mobile_identifier_hash TEXT PRIMARY KEY, - imsi TEXT, - mac_addr TEXT, - eap_method TEXT, - timestamp TEXT -); diff --git a/contrib/wpa/hs20/server/www/add-free.php b/contrib/wpa/hs20/server/www/add-free.php deleted file mode 100644 index 1efc65563274..000000000000 --- a/contrib/wpa/hs20/server/www/add-free.php +++ /dev/null @@ -1,50 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; -$realm = $row['realm']; - -$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch(); -if (!$row || strlen($row['value']) == 0) { - die("Free account disabled"); -} - -$user = $row['value']; - -$row = $db->query("SELECT password FROM users WHERE identity='$user' AND realm='$realm'")->fetch(); -if (!$row) - die("Free account not found"); - -$pw = $row['password']; - -if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', machine_managed='1' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for a new PPS MO')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/add-mo.php b/contrib/wpa/hs20/server/www/add-mo.php deleted file mode 100644 index a3b4513531f8..000000000000 --- a/contrib/wpa/hs20/server/www/add-mo.php +++ /dev/null @@ -1,56 +0,0 @@ -

Invalid username

\n"; - echo "Try again\n"; - echo "\n"; - exit; -} - -$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} -$realm = $row['realm']; - -$userrow = $db->query("SELECT identity FROM users WHERE identity='$user' AND realm='$realm'")->fetch(); -if ($userrow) { - echo "

Selected username is not available

\n"; - echo "Try again\n"; - echo "\n"; - exit; -} - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; - -if (!$db->exec("UPDATE sessions SET user='$user', password='$pw', realm='$realm', type='password' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for a new PPS MO')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/cert-enroll.php b/contrib/wpa/hs20/server/www/cert-enroll.php deleted file mode 100644 index f023ca5a5b03..000000000000 --- a/contrib/wpa/hs20/server/www/cert-enroll.php +++ /dev/null @@ -1,39 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; -$realm = $row['realm']; - -$user = sha1(mt_rand()); - -if (!$db->exec("UPDATE sessions SET user='$user', type='cert' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for client certificate enrollment')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/config.php b/contrib/wpa/hs20/server/www/config.php deleted file mode 100644 index 4272b102a88c..000000000000 --- a/contrib/wpa/hs20/server/www/config.php +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/contrib/wpa/hs20/server/www/est.php b/contrib/wpa/hs20/server/www/est.php deleted file mode 100644 index b7fb260d56c4..000000000000 --- a/contrib/wpa/hs20/server/www/est.php +++ /dev/null @@ -1,232 +0,0 @@ -1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, - 'uri'=>1, 'response'=>1); - $data = array(); - $keys = implode('|', array_keys($needed)); - preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', - $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER); - foreach ($matches as $m) { - $data[$m[1]] = $m[3] ? $m[3] : $m[4]; - unset($needed[$m[1]]); - } - if ($needed) { - error_log("EST: Missing auth parameter"); - die('Authentication failed'); - } - $user = $data['username']; - if (strlen($user) < 1) { - error_log("EST: Empty username"); - die('Authentication failed'); - } - - $sql = "SELECT rowid,password,operation FROM sessions " . - "WHERE user='$user' AND realm='$realm'"; - $q = $db->query($sql); - if (!$q) { - error_log("EST: Session not found for user=$user realm=$realm"); - die("Session not found"); - } - $row = $q->fetch(); - if (!$row) { - error_log("EST: Session fetch failed for user=$user realm=$realm"); - die('Session not found'); - } - $rowid = $row['rowid']; - - $oper = $row['operation']; - if ($oper != '5') { - error_log("EST: Unexpected operation $oper for user=$user realm=$realm"); - die("Session not found"); - } - $pw = $row['password']; - if (strlen($pw) < 1) { - error_log("EST: Empty password for user=$user realm=$realm"); - die('Authentication failed'); - } - - $A1 = md5($user . ':' . $realm . ':' . $pw); - $A2 = md5($method . ':' . $data['uri']); - $resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . - $data['cnonce'] . ':' . $data['qop'] . ':' . $A2); - if ($data['response'] != $resp) { - error_log("EST: Incorrect authentication response for user=$user realm=$realm"); - die('Authentication failed'); - } -} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) && - $_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" && - isset($_SERVER["SSL_CLIENT_M_SERIAL"])) { - $user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"]; - $sql = "SELECT rowid,password,operation FROM sessions " . - "WHERE user='$user' AND realm='$realm'"; - $q = $db->query($sql); - if (!$q) { - error_log("EST: Session not found for user=$user realm=$realm"); - die("Session not found"); - } - $row = $q->fetch(); - if (!$row) { - error_log("EST: Session fetch failed for user=$user realm=$realm"); - die('Session not found'); - } - $rowid = $row['rowid']; - - $oper = $row['operation']; - if ($oper != '10') { - error_log("EST: Unexpected operation $oper for user=$user realm=$realm"); - die("Session not found"); - } -} - - -if ($method == "GET" && $cmd == "cacerts") { - $fname = "$osu_root/est/$realm-cacerts.pkcs7"; - if (!file_exists($fname)) { - error_log("EST: cacerts - unknown realm $realm"); - die("Unknown realm"); - } - - header("Content-Transfer-Encoding: base64"); - header("Content-Type: application/pkcs7-mime"); - - $data = file_get_contents($fname); - echo wordwrap(base64_encode($data), 72, "\n", true); - echo "\n"; - error_log("EST: cacerts"); -} else if ($method == "GET" && $cmd == "csrattrs") { - header("Content-Transfer-Encoding: base64"); - header("Content-Type: application/csrattrs"); - readfile("$osu_root/est/est-attrs.b64"); - error_log("EST: csrattrs"); -} else if ($method == "POST" && - ($cmd == "simpleenroll" || $cmd == "simplereenroll")) { - $reenroll = $cmd == "simplereenroll"; - if (!$reenroll && (!isset($user) || strlen($user) == 0)) { - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: Digest realm="'.$realm. - '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); - error_log("EST: simpleenroll - require authentication"); - die('Authentication required'); - } - if ($reenroll && - (!isset($user) || - !isset($_SERVER["SSL_CLIENT_VERIFY"]) || - $_SERVER["SSL_CLIENT_VERIFY"] != "SUCCESS")) { - header('HTTP/1.1 403 Forbidden'); - error_log("EST: simplereenroll - require certificate authentication"); - die('Authentication required'); - } - if (!isset($_SERVER["CONTENT_TYPE"])) { - error_log("EST: simpleenroll without Content-Type"); - die("Missing Content-Type"); - } - if (!stristr($_SERVER["CONTENT_TYPE"], "application/pkcs10")) { - error_log("EST: simpleenroll - unexpected Content-Type: " . - $_SERVER["CONTENT_TYPE"]); - die("Unexpected Content-Type"); - } - - $data = file_get_contents("php://input"); - error_log("EST: simpleenroll - POST data from php://input: " . $data); - $req = base64_decode($data); - if ($req == FALSE) { - error_log("EST: simpleenroll - Invalid base64-encoded PKCS#10 data"); - die("Invalid base64-encoded PKCS#10 data"); - } - $cadir = "$osu_root/est"; - $reqfile = "$cadir/tmp/cert-req.pkcs10"; - $f = fopen($reqfile, "wb"); - fwrite($f, $req); - fclose($f); - - $req_pem = "$reqfile.pem"; - if (file_exists($req_pem)) - unlink($req_pem); - exec("openssl req -in $reqfile -inform DER -out $req_pem -outform PEM"); - if (!file_exists($req_pem)) { - error_log("EST: simpleenroll - Failed to parse certificate request"); - die("Failed to parse certificate request"); - } - - /* FIX: validate request and add HS 2.0 extensions to cert */ - $cert_pem = "$cadir/tmp/req-signed.pem"; - if (file_exists($cert_pem)) - unlink($cert_pem); - exec("openssl x509 -req -in $req_pem -CAkey $cadir/cakey.pem -out $cert_pem -CA $cadir/cacert.pem -CAserial $cadir/serial -days 365 -text"); - if (!file_exists($cert_pem)) { - error_log("EST: simpleenroll - Failed to sign certificate"); - die("Failed to sign certificate"); - } - - $cert = file_get_contents($cert_pem); - $handle = popen("openssl x509 -in $cert_pem -serial -noout", "r"); - $serial = fread($handle, 200); - pclose($handle); - $pattern = "/serial=(?P[0-9a-fA-F:]*)/m"; - preg_match($pattern, $serial, $matches); - if (!isset($matches['snhex']) || strlen($matches['snhex']) < 1) { - error_log("EST: simpleenroll - Could not get serial number"); - die("Could not get serial number"); - } - $sn = str_replace(":", "", strtoupper($matches['snhex'])); - - $user = "cert-$sn"; - error_log("EST: user = $user"); - - $cert_der = "$cadir/tmp/req-signed.der"; - if (file_exists($cert_der)) - unlink($cert_der); - exec("openssl x509 -in $cert_pem -inform PEM -out $cert_der -outform DER"); - if (!file_exists($cert_der)) { - error_log("EST: simpleenroll - Failed to convert certificate"); - die("Failed to convert certificate"); - } - $der = file_get_contents($cert_der); - $fingerprint = hash("sha256", $der); - error_log("EST: sha256(DER cert): $fingerprint"); - - $pkcs7 = "$cadir/tmp/est-client.pkcs7"; - if (file_exists($pkcs7)) - unlink($pkcs7); - exec("openssl crl2pkcs7 -nocrl -certfile $cert_pem -out $pkcs7 -outform DER"); - if (!file_exists($pkcs7)) { - error_log("EST: simpleenroll - Failed to prepare PKCS#7 file"); - die("Failed to prepare PKCS#7 file"); - } - - if (!$db->exec("UPDATE sessions SET user='$user', cert='$fingerprint', cert_pem='$cert' WHERE rowid=$rowid")) { - error_log("EST: simpleenroll - Failed to update session database"); - die("Failed to update session database"); - } - - header("Content-Transfer-Encoding: base64"); - header("Content-Type: application/pkcs7-mime"); - - $data = file_get_contents($pkcs7); - $resp = wordwrap(base64_encode($data), 72, "\n", true); - echo $resp . "\n"; - error_log("EST: simpleenroll - PKCS#7 response: " . $resp); -} else { - header("HTTP/1.0 404 Not Found"); - error_log("EST: Unexpected method or path"); - die("Unexpected method or path"); -} - -?> diff --git a/contrib/wpa/hs20/server/www/free-remediation.php b/contrib/wpa/hs20/server/www/free-remediation.php deleted file mode 100644 index 5648b30e8d6b..000000000000 --- a/contrib/wpa/hs20/server/www/free-remediation.php +++ /dev/null @@ -1,19 +0,0 @@ - - -Hotspot 2.0 - public and free hotspot - remediation - - - -

Hotspot 2.0 - public and free hotspot

- -

Terms and conditions have changed. You need to accept the new terms -to continue using this network.

- -

Terms and conditions..

- -Accept
\n"; -?> - - - diff --git a/contrib/wpa/hs20/server/www/free.php b/contrib/wpa/hs20/server/www/free.php deleted file mode 100644 index 8195069ed8ff..000000000000 --- a/contrib/wpa/hs20/server/www/free.php +++ /dev/null @@ -1,23 +0,0 @@ - - -Hotspot 2.0 - public and free hotspot - - - -Hotspot 2.0 - public and free hotspot\n"; - -echo "
\n"; -echo "\n"; - -?> - -

Terms and conditions..

- -
- - - diff --git a/contrib/wpa/hs20/server/www/redirect.php b/contrib/wpa/hs20/server/www/redirect.php deleted file mode 100644 index 8fc9cd644273..000000000000 --- a/contrib/wpa/hs20/server/www/redirect.php +++ /dev/null @@ -1,32 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$uri = $row['redirect_uri']; - -header("Location: $uri", true, 302); - -$user = $row['user']; -$realm = $row['realm']; - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'redirected after user input')"); - -?> diff --git a/contrib/wpa/hs20/server/www/remediation-pw.php b/contrib/wpa/hs20/server/www/remediation-pw.php deleted file mode 100644 index 76fdccbdf9f7..000000000000 --- a/contrib/wpa/hs20/server/www/remediation-pw.php +++ /dev/null @@ -1,41 +0,0 @@ -query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} -$user = $row['user']; -$realm = $row['realm']; - -$uri = $row['redirect_uri']; -$rowid = $row['rowid']; - -if (!$db->exec("UPDATE sessions SET password='$pw' WHERE rowid=$rowid")) { - die("Failed to update session database"); -} - -$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " . - "VALUES ('$user', '$realm', '$id', " . - "strftime('%Y-%m-%d %H:%M:%f','now'), " . - "'completed user input response for subscription remediation')"); - -header("Location: $uri", true, 302); - -?> diff --git a/contrib/wpa/hs20/server/www/remediation.php b/contrib/wpa/hs20/server/www/remediation.php deleted file mode 100644 index 3628065ac225..000000000000 --- a/contrib/wpa/hs20/server/www/remediation.php +++ /dev/null @@ -1,55 +0,0 @@ - - -Hotspot 2.0 subscription remediation - - - -\n"; - -$row = $db->query("SELECT * FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found"); -} - -$username = $row['user']; -echo "User: " . $username . "@" . $row['realm'] . "
\n"; - -$user = $db->query("SELECT machine_managed,methods FROM users WHERE identity='$username'")->fetch(); -if ($user == false) { - die("User not found"); -} - -echo "

\n"; - -$cert = $user['methods'] == "TLS" || strncmp($username, "cert-", 5) == 0; - -if ($cert) { - echo "Complete user subscription remediation
\n"; -} else if ($user['machine_managed'] == "1") { - echo "Complete user subscription remediation
\n"; - echo "This will provide a new machine-generated password.
\n"; -} else { - echo "
\n"; - echo "\n"; - echo "New password:
\n"; - echo "\n"; - echo "
\n"; -} - -?> - - - diff --git a/contrib/wpa/hs20/server/www/signup.php b/contrib/wpa/hs20/server/www/signup.php deleted file mode 100644 index 80a9d403e8fc..000000000000 --- a/contrib/wpa/hs20/server/www/signup.php +++ /dev/null @@ -1,59 +0,0 @@ - - -Hotspot 2.0 signup - - - -query("SELECT realm,test FROM sessions WHERE id='$id'")->fetch(); -if ($row == false) { - die("Session not found for id: $id"); -} -$realm = $row['realm']; -$test = $row['test']; - -if (strlen($test) > 0) { - echo "

Special test functionality: $test

\n"; -} - -echo "

Sign up for a subscription - $realm

\n"; - -echo "

This page can be used to select between three different types of subscriptions for testing purposes.

\n"; - -echo "

Option 1 - shared free access credential

\n"; - -$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch(); -if ($row && strlen($row['value']) > 0) { - echo "

Sign up for free access

\n"; -} - -echo "

Option 2 - username/password credential

\n"; - -echo "
\n"; -echo "\n"; -?> -Select a username and password. Leave password empty to get automatically -generated and machine managed password.
-Username:
-Password:
- -
- -Option 3 - client certificate credential\n"; - -echo "

Enroll a client certificate

\n" -?> - - - diff --git a/contrib/wpa/hs20/server/www/spp.php b/contrib/wpa/hs20/server/www/spp.php deleted file mode 100644 index c56d3d69e0ed..000000000000 --- a/contrib/wpa/hs20/server/www/spp.php +++ /dev/null @@ -1,168 +0,0 @@ -1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, - 'uri'=>1, 'response'=>1); - $data = array(); - $keys = implode('|', array_keys($needed)); - preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', - $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER); - foreach ($matches as $m) { - $data[$m[1]] = $m[3] ? $m[3] : $m[4]; - unset($needed[$m[1]]); - } - if ($needed) { - error_log("spp.php - Authentication failed - missing: " . print_r($needed)); - die('Authentication failed'); - } - $user = $data['username']; - if (strlen($user) < 1) { - error_log("spp.php - Authentication failed - empty username"); - die('Authentication failed'); - } - - - $db = new PDO($osu_db); - if (!$db) { - error_log("spp.php - Could not access database"); - die("Could not access database"); - } - $row = $db->query("SELECT password FROM users " . - "WHERE identity='$user' AND realm='$realm'")->fetch(); - if (!$row) { - $row = $db->query("SELECT osu_password FROM users " . - "WHERE osu_user='$user' AND realm='$realm'")->fetch(); - $pw = $row['osu_password']; - } else - $pw = $row['password']; - if (!$row) { - error_log("spp.php - Authentication failed - user '$user' not found"); - die('Authentication failed'); - } - if (strlen($pw) < 1) { - error_log("spp.php - Authentication failed - empty password"); - die('Authentication failed'); - } - - $A1 = md5($user . ':' . $realm . ':' . $pw); - $A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $data['uri']); - $resp = md5($A1 . ':' . $data['nonce'] . ':' . $data['nc'] . ':' . - $data['cnonce'] . ':' . $data['qop'] . ':' . $A2); - if ($data['response'] != $resp) { - error_log("Authentication failure - response mismatch"); - die('Authentication failed'); - } -} else if (isset($_SERVER["SSL_CLIENT_VERIFY"]) && - $_SERVER["SSL_CLIENT_VERIFY"] == "SUCCESS" && - isset($_SERVER["SSL_CLIENT_M_SERIAL"])) { - $user = "cert-" . $_SERVER["SSL_CLIENT_M_SERIAL"]; - putenv("HS20CERT=yes"); -} else if (isset($_GET["hotspot2dot0-mobile-identifier-hash"])) { - $id_hash = $_GET["hotspot2dot0-mobile-identifier-hash"]; - $id_hash = PREG_REPLACE("/[^0-9a-h]/i", '', $id_hash); - - $db = new PDO($osu_db); - if (!$db) { - error_log("spp.php - Could not access database"); - die("Could not access database"); - } - - $row = $db->query("SELECT * FROM sim_provisioning " . - "WHERE mobile_identifier_hash='$id_hash'")->fetch(); - if (!$row) { - error_log("spp.php - SIM provisioning failed - mobile_identifier_hash not found"); - die('SIM provisioning failed - mobile_identifier_hash not found'); - } - - $imsi = $row['imsi']; - $mac_addr = $row['mac_addr']; - $eap_method = $row['eap_method']; - - $row = $db->query("SELECT COUNT(*) FROM osu_config " . - "WHERE realm='$realm'")->fetch(); - if (!$row || intval($row[0]) < 1) { - error_log("spp.php - SIM provisioning failed - realm $realm not found"); - die('SIM provisioning failed'); - } - - error_log("spp.php - SIM provisioning for IMSI $imsi"); - putenv("HS20SIMPROV=yes"); - putenv("HS20IMSI=$imsi"); - putenv("HS20MACADDR=$mac_addr"); - putenv("HS20EAPMETHOD=$eap_method"); - putenv("HS20IDHASH=$id_hash"); -} else if (!isset($_SERVER["PATH_INFO"]) || - $_SERVER["PATH_INFO"] != "/signup") { - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: Digest realm="'.$realm. - '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); - error_log("spp.php - Authentication required (not signup)"); - die('Authentication required (not signup)'); -} - - -if (isset($user) && strlen($user) > 0) - putenv("HS20USER=$user"); -else - putenv("HS20USER"); - -putenv("HS20REALM=$realm"); -$postdata = file_get_contents("php://input"); -putenv("HS20POST=$postdata"); -$addr = $_SERVER["REMOTE_ADDR"]; -putenv("HS20ADDR=$addr"); -putenv("HS20TEST=$test"); - -$last = exec("$osu_root/spp/hs20_spp_server -r$osu_root -f/tmp/hs20_spp_server.log", $output, $ret); - -if ($ret == 2) { - if (empty($_SERVER['PHP_AUTH_DIGEST'])) { - header('HTTP/1.1 401 Unauthorized'); - header('WWW-Authenticate: Digest realm="'.$realm. - '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); - error_log("spp.php - Authentication required (ret 2)"); - die('Authentication required'); - } else { - error_log("spp.php - Unexpected authentication error"); - die("Unexpected authentication error"); - } -} -if ($ret != 0) { - error_log("spp.php - Failed to process SPP request"); - die("Failed to process SPP request"); -} -//error_log("spp.php: Response: " . implode($output)); - -header("Content-Type: application/soap+xml"); - -echo implode($output); - -?> diff --git a/contrib/wpa/hs20/server/www/terms.php b/contrib/wpa/hs20/server/www/terms.php deleted file mode 100644 index acba23ef1ad7..000000000000 --- a/contrib/wpa/hs20/server/www/terms.php +++ /dev/null @@ -1,87 +0,0 @@ -\n"; - echo "HS 2.0 Terms and Conditions\n"; - echo "\n"; -} - -$db = new PDO($osu_db); -if (!$db) { - die($sqliteerror); -} - -if (!isset($_GET["addr"])) { - die("Missing addr parameter"); -} -$addr = $_GET["addr"]; - -$accept = isset($_GET["accept"]) && $_GET["accept"] == "yes"; - -$res = $db->prepare("SELECT identity FROM pending_tc WHERE mac_addr=?"); -$res->execute(array($addr)); -$row = $res->fetch(); -if (!$row) { - die("No pending session for the specified MAC address"); -} -$identity = $row[0]; - -if (!$accept) { - print_header(); - - echo "

Accept the following terms and conditions by clicking here: Accept

\n
\n"; - readfile($t_c_file); -} else { - $res = $db->prepare("UPDATE users SET t_c_timestamp=? WHERE identity=?"); - if (!$res->execute(array($t_c_timestamp, $identity))) { - die("Failed to update user account."); - } - - $res = $db->prepare("DELETE FROM pending_tc WHERE mac_addr=?"); - $res->execute(array($addr)); - - $fp = fsockopen($hostapd_ctrl); - if (!$fp) { - die("Could not connect to hostapd(AS)"); - } - - fwrite($fp, "DAC_REQUEST coa $addr t_c_clear"); - fclose($fp); - - $waiting = true; - $ack = false; - for ($i = 1; $i <= 10; $i++) { - $res = $db->prepare("SELECT waiting_coa_ack,coa_ack_received FROM current_sessions WHERE mac_addr=?"); - $res->execute(array($addr)); - $row = $res->fetch(); - if (!$row) { - die("No current session for the specified MAC address"); - } - if (strlen($row[0]) > 0) - $waiting = $row[0] == 1; - if (strlen($row[1]) > 0) - $ack = $row[1] == 1; - $res->closeCursor(); - if (!$waiting) - break; - sleep(1); - } - if ($ack) { - header('X-WFA-Hotspot20-Filtering: removed'); - print_header(); - echo "

Terms and conditions were accepted.

\n"; - - echo "

Filtering disabled.

\n"; - } else { - print_header(); - echo "

Failed to disable filtering.

\n"; - } -} - -?> - - - diff --git a/contrib/wpa/hs20/server/www/users.php b/contrib/wpa/hs20/server/www/users.php deleted file mode 100644 index 2bd555275dda..000000000000 --- a/contrib/wpa/hs20/server/www/users.php +++ /dev/null @@ -1,377 +0,0 @@ - 0) { - $row = $db->query("SELECT dump FROM eventlog WHERE rowid=$id")->fetch(); - $dump = $row['dump']; - if ($dump[0] == '<') { - header("Content-type: text/xml"); - echo "\n"; - echo $dump; - } else { - header("Content-type: text/plain"); - echo $dump; - } - exit; -} - -if ($cmd == 'mo' && $id > 0) { - $mo = $_GET["mo"]; - if (!isset($mo)) - exit; - if ($mo != "devinfo" && $mo != "devdetail" && $mo != "pps") - exit; - $row = $db->query("SELECT $mo FROM users WHERE rowid=$id")->fetch(); - header("Content-type: text/xml"); - echo "\n"; - echo $row[$mo]; - exit; -} - -if ($cmd == 'cert' && $id > 0) { - $row = $db->query("SELECT cert_pem FROM users WHERE rowid=$id")->fetch(); - header("Content-type: text/plain"); - echo $row['cert_pem']; - exit; -} - -?> - - -HS 2.0 users - - - 0) { - $db->exec("UPDATE users SET remediation='' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-user' && $id > 0) { - $db->exec("UPDATE users SET remediation='user' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-machine' && $id > 0) { - $db->exec("UPDATE users SET remediation='machine' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-reenroll' && $id > 0) { - $db->exec("UPDATE users SET remediation='reenroll' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-policy' && $id > 0) { - $db->exec("UPDATE users SET remediation='policy' WHERE rowid=$id"); -} -if ($cmd == 'subrem-add-free' && $id > 0) { - $db->exec("UPDATE users SET remediation='free' WHERE rowid=$id"); -} -if ($cmd == 'fetch-pps-on' && $id > 0) { - $db->exec("UPDATE users SET fetch_pps=1 WHERE rowid=$id"); -} -if ($cmd == 'fetch-pps-off' && $id > 0) { - $db->exec("UPDATE users SET fetch_pps=0 WHERE rowid=$id"); -} -if ($cmd == 'reset-pw' && $id > 0) { - $db->exec("UPDATE users SET password='ChangeMe' WHERE rowid=$id"); -} -if ($cmd == "policy" && $id > 0 && isset($_GET["policy"])) { - $policy = $_GET["policy"]; - if ($policy == "no-policy" || - is_readable("$osu_root/spp/policy/$policy.xml")) { - $db->exec("UPDATE users SET policy='$policy' WHERE rowid=$id"); - } -} -if ($cmd == "account-type" && $id > 0 && isset($_GET["type"])) { - $type = $_GET["type"]; - if ($type == "shared") - $db->exec("UPDATE users SET shared=1 WHERE rowid=$id"); - if ($type == "default") - $db->exec("UPDATE users SET shared=0 WHERE rowid=$id"); -} - -if ($cmd == "set-osu-cred" && $id > 0) { - $osu_user = $_POST["osu_user"]; - $osu_password = $_POST["osu_password"]; - if (strlen($osu_user) == 0) - $osu_password = ""; - $db->exec("UPDATE users SET osu_user='$osu_user', osu_password='$osu_password' WHERE rowid=$id"); -} - -if ($cmd == 'clear-t-c' && $id > 0) { - $db->exec("UPDATE users SET t_c_timestamp=NULL WHERE rowid=$id"); -} - -$dump = 0; - -if ($id > 0) { - -if (isset($_GET["dump"])) { - $dump = $_GET["dump"]; - if (!is_numeric($dump)) - $dump = 0; -} else - $dump = 0; - -echo "[All users] "; -if ($dump == 0) - echo "[Include debug dump] "; -else - echo "[Without debug dump] "; -echo "
\n"; - -$row = $db->query("SELECT rowid,* FROM users WHERE rowid=$id")->fetch(); - -echo "

" . $row['identity'] . "@" . $row['realm'] . "

\n"; - -echo "MO: "; -if (strlen($row['devinfo']) > 0) { - echo "[DevInfo]\n"; -} -if (strlen($row['devdetail']) > 0) { - echo "[DevDetail]\n"; -} -if (strlen($row['pps']) > 0) { - echo "[PPS]\n"; -} -if (strlen($row['cert_pem']) > 0) { - echo "[Certificate]\n"; -} -echo "
\n"; - -echo "Fetch PPS MO: "; -if ($row['fetch_pps'] == "1") { - echo "On next connection " . - "[" . - "do not fetch]
\n"; -} else { - echo "Do not fetch " . - "[" . - "request fetch]
\n"; -} - -$cert = $row['cert']; -if (strlen($cert) > 0) { - echo "Certificate fingerprint: $cert
\n"; -} - -echo "Remediation: "; -$rem = $row['remediation']; -if ($rem == "") { - echo "Not required"; - echo " [add:user]"; - echo " [add:machine]"; - if ($row['methods'] == 'TLS') { - echo " [add:reenroll]"; - } - echo " [add:policy]"; - echo " [add:free]"; -} else if ($rem == "user") { - echo "User [clear]"; -} else if ($rem == "policy") { - echo "Policy [clear]"; -} else if ($rem == "free") { - echo "Free [clear]"; -} else if ($rem == "reenroll") { - echo "Reenroll [clear]"; -} else { - echo "Machine [clear]"; -} -echo "
\n"; - -if (strncmp($row['identity'], "cert-", 5) != 0) - echo "Machine managed: " . ($row['machine_managed'] == "1" ? "TRUE" : "FALSE") . "
\n"; - -echo "
Policy:
\n"; - -echo "
Account type:
\n"; - -echo "Phase 2 method(s): " . $row['methods'] . "
\n"; - -echo "
\n"; -echo "Reset AAA password
\n"; - -echo "
\n"; -echo "
\n"; -echo "OSU credentials (if username empty, AAA credentials are used):
\n"; -echo "username: \n"; -echo "password: \n"; -echo "\n"; -echo "
\n"; - -if (strlen($row['t_c_timestamp']) > 0) { - echo "
\n"; - echo "Clear Terms and Conditions acceptance
\n"; -} - -echo "
\n"; - -$user = $row['identity']; -$osu_user = $row['osu_user']; -$realm = $row['realm']; -} - -if ($id > 0 || ($id == 0 && $cmd == 'eventlog')) { - - if ($id == 0) { - echo "[All users] "; - echo "
\n"; - } - -echo "\n"; -echo ""; -if ($id == 0) { - echo ""; - if ($id == 0) { - echo "
userrealm"; -} -echo "timeaddresssessionIDnotes"; -if ($dump > 0) - echo "dump"; -echo "\n"; -if (isset($_GET["limit"])) { - $limit = $_GET["limit"]; - if (!is_numeric($limit)) - $limit = 20; -} else - $limit = 20; -if ($id == 0) - $res = $db->query("SELECT rowid,* FROM eventlog ORDER BY timestamp DESC LIMIT $limit"); -else if (strlen($osu_user) > 0) - $res = $db->query("SELECT rowid,* FROM eventlog WHERE (user='$user' OR user='$osu_user') AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit"); -else - $res = $db->query("SELECT rowid,* FROM eventlog WHERE user='$user' AND realm='$realm' ORDER BY timestamp DESC LIMIT $limit"); -foreach ($res as $row) { - echo "
" . $row['user'] . "\n"; - echo "" . $row['realm'] . "\n"; - } - echo "" . $row['timestamp'] . "\n"; - echo "" . $row['addr'] . "\n"; - echo "" . $row['sessionid'] . "\n"; - echo "" . $row['notes'] . "\n"; - $d = $row['dump']; - if (strlen($d) > 0) { - echo "["; - if ($d[0] == '<') - echo "XML"; - else - echo "txt"; - echo "]\n"; - if ($dump > 0) - echo "" . htmlspecialchars($d) . "\n"; - } -} -echo "
\n"; - -} - - -if ($id == 0 && $cmd != 'eventlog') { - -echo "[Eventlog] "; -echo "
\n"; - -echo "\n"; -echo "
UserRealmRemediationPolicyAccount typePhase 2 method(s)DevIdMAC AddressT&C\n"; - -$res = $db->query('SELECT rowid,* FROM users WHERE (phase2=1 OR methods=\'TLS\') ORDER BY identity'); -foreach ($res as $row) { - echo "
" . - $row['identity'] . " "; - echo "" . $row['realm']; - $rem = $row['remediation']; - echo ""; - if ($rem == "") { - echo "-"; - } else if ($rem == "user") { - echo "User"; - } else if ($rem == "policy") { - echo "Policy"; - } else if ($rem == "free") { - echo "Free"; - } else if ($rem == "reenroll") { - echo "Reenroll"; - } else { - echo "Machine"; - } - echo "" . $row['policy']; - if ($row['shared'] > 0) - echo "shared"; - else - echo "default"; - echo "" . $row['methods'] . ""; - echo ""; - $xml = xml_parser_create(); - xml_parse_into_struct($xml, $row['devinfo'], $devinfo); - foreach($devinfo as $k) { - if ($k['tag'] == 'DEVID') { - echo "" . $k['value'] . ""; - break; - } - } - echo "" . $row['mac_addr'] . ""; - echo "" . $row['t_c_timestamp'] . ""; - echo "\n"; -} -echo "
\n"; - -} - -?> - - diff --git a/contrib/wpa/src/common/dragonfly.c b/contrib/wpa/src/common/dragonfly.c index 547be66f1561..1e842716668e 100644 --- a/contrib/wpa/src/common/dragonfly.c +++ b/contrib/wpa/src/common/dragonfly.c @@ -1,215 +1,249 @@ /* * Shared Dragonfly functionality * Copyright (c) 2012-2016, Jouni Malinen * Copyright (c) 2019, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "utils/includes.h" #include "utils/common.h" #include "utils/const_time.h" #include "crypto/crypto.h" #include "dragonfly.h" int dragonfly_suitable_group(int group, int ecc_only) { /* Enforce REVmd rules on which SAE groups are suitable for production * purposes: FFC groups whose prime is >= 3072 bits and ECC groups * defined over a prime field whose prime is >= 256 bits. Furthermore, * ECC groups defined over a characteristic 2 finite field and ECC * groups with a co-factor greater than 1 are not suitable. Disable * groups that use Brainpool curves as well for now since they leak more * timing information due to the prime not being close to a power of * two. */ return group == 19 || group == 20 || group == 21 || (!ecc_only && (group == 15 || group == 16 || group == 17 || group == 18)); } unsigned int dragonfly_min_pwe_loop_iter(int group) { if (group == 22 || group == 23 || group == 24) { /* FFC groups for which pwd-value is likely to be >= p * frequently */ return 40; } if (group == 1 || group == 2 || group == 5 || group == 14 || group == 15 || group == 16 || group == 17 || group == 18) { /* FFC groups that have prime that is close to a power of two */ return 1; } /* Default to 40 (this covers most ECC groups) */ return 40; } int dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime, struct crypto_bignum **qr, struct crypto_bignum **qnr) { *qr = *qnr = NULL; while (!(*qr) || !(*qnr)) { struct crypto_bignum *tmp; int res; tmp = crypto_bignum_init(); if (!tmp || crypto_bignum_rand(tmp, prime) < 0) { crypto_bignum_deinit(tmp, 0); break; } res = crypto_bignum_legendre(tmp, prime); if (res == 1 && !(*qr)) *qr = tmp; else if (res == -1 && !(*qnr)) *qnr = tmp; else crypto_bignum_deinit(tmp, 0); } if (*qr && *qnr) return 0; crypto_bignum_deinit(*qr, 0); crypto_bignum_deinit(*qnr, 0); *qr = *qnr = NULL; return -1; } static struct crypto_bignum * dragonfly_get_rand_1_to_p_1(const struct crypto_bignum *prime) { struct crypto_bignum *tmp, *pm1, *one; tmp = crypto_bignum_init(); pm1 = crypto_bignum_init(); one = crypto_bignum_init_set((const u8 *) "\x01", 1); if (!tmp || !pm1 || !one || crypto_bignum_sub(prime, one, pm1) < 0 || crypto_bignum_rand(tmp, pm1) < 0 || crypto_bignum_add(tmp, one, tmp) < 0) { crypto_bignum_deinit(tmp, 0); tmp = NULL; } crypto_bignum_deinit(pm1, 0); crypto_bignum_deinit(one, 0); return tmp; } int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec, const u8 *qr, const u8 *qnr, const struct crypto_bignum *val) { struct crypto_bignum *r, *num, *qr_or_qnr = NULL; int check, res = -1; u8 qr_or_qnr_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; const struct crypto_bignum *prime; size_t prime_len; unsigned int mask; prime = crypto_ec_get_prime(ec); prime_len = crypto_ec_prime_len(ec); /* * Use a blinding technique to mask val while determining whether it is * a quadratic residue modulo p to avoid leaking timing information * while determining the Legendre symbol. * * v = val * r = a random number between 1 and p-1, inclusive * num = (v * r * r) modulo p */ r = dragonfly_get_rand_1_to_p_1(prime); if (!r) return -1; num = crypto_bignum_init(); if (!num || crypto_bignum_mulmod(val, r, prime, num) < 0 || crypto_bignum_mulmod(num, r, prime, num) < 0) goto fail; /* * Need to minimize differences in handling different cases, so try to * avoid branches and timing differences. * * If r is odd: * num = (num * qr) module p * LGR(num, p) = 1 ==> quadratic residue * else: * num = (num * qnr) module p * LGR(num, p) = -1 ==> quadratic residue * * mask is set to !odd(r) */ mask = const_time_is_zero(crypto_bignum_is_odd(r)); const_time_select_bin(mask, qnr, qr, prime_len, qr_or_qnr_bin); qr_or_qnr = crypto_bignum_init_set(qr_or_qnr_bin, prime_len); if (!qr_or_qnr || crypto_bignum_mulmod(num, qr_or_qnr, prime, num) < 0) goto fail; /* branchless version of check = odd(r) ? 1 : -1, */ check = const_time_select_int(mask, -1, 1); /* Determine the Legendre symbol on the masked value */ res = crypto_bignum_legendre(num, prime); if (res == -2) { res = -1; goto fail; } /* branchless version of res = res == check * (res is -1, 0, or 1; check is -1 or 1) */ mask = const_time_eq(res, check); res = const_time_select_int(mask, 1, 0); fail: crypto_bignum_deinit(num, 1); crypto_bignum_deinit(r, 1); crypto_bignum_deinit(qr_or_qnr, 1); return res; } static int dragonfly_get_rand_2_to_r_1(struct crypto_bignum *val, const struct crypto_bignum *order) { return crypto_bignum_rand(val, order) == 0 && !crypto_bignum_is_zero(val) && !crypto_bignum_is_one(val); } int dragonfly_generate_scalar(const struct crypto_bignum *order, struct crypto_bignum *_rand, struct crypto_bignum *_mask, struct crypto_bignum *scalar) { int count; /* Select two random values rand,mask such that 1 < rand,mask < r and * rand + mask mod r > 1. */ for (count = 0; count < 100; count++) { if (dragonfly_get_rand_2_to_r_1(_rand, order) && dragonfly_get_rand_2_to_r_1(_mask, order) && crypto_bignum_add(_rand, _mask, scalar) == 0 && crypto_bignum_mod(scalar, order, scalar) == 0 && !crypto_bignum_is_zero(scalar) && !crypto_bignum_is_one(scalar)) return 0; } /* This should not be reachable in practice if the random number * generation is working. */ wpa_printf(MSG_INFO, "dragonfly: Unable to get randomness for own scalar"); return -1; } + + +/* res = sqrt(val) */ +int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, + struct crypto_bignum *res) +{ + const struct crypto_bignum *prime; + struct crypto_bignum *tmp, *one; + int ret = 0; + u8 prime_bin[DRAGONFLY_MAX_ECC_PRIME_LEN]; + size_t prime_len; + + /* For prime p such that p = 3 mod 4, sqrt(w) = w^((p+1)/4) mod p */ + + prime = crypto_ec_get_prime(ec); + prime_len = crypto_ec_prime_len(ec); + tmp = crypto_bignum_init(); + one = crypto_bignum_init_uint(1); + + if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), + prime_len) < 0 || + (prime_bin[prime_len - 1] & 0x03) != 3 || + !tmp || !one || + /* tmp = (p+1)/4 */ + crypto_bignum_add(prime, one, tmp) < 0 || + crypto_bignum_rshift(tmp, 2, tmp) < 0 || + /* res = sqrt(val) */ + crypto_bignum_exptmod(val, tmp, prime, res) < 0) + ret = -1; + + crypto_bignum_deinit(tmp, 0); + crypto_bignum_deinit(one, 0); + return ret; +} diff --git a/contrib/wpa/src/common/dragonfly.h b/contrib/wpa/src/common/dragonfly.h index ec3dd593eda4..84d67f575c54 100644 --- a/contrib/wpa/src/common/dragonfly.h +++ b/contrib/wpa/src/common/dragonfly.h @@ -1,31 +1,33 @@ /* * Shared Dragonfly functionality * Copyright (c) 2012-2016, Jouni Malinen * Copyright (c) 2019, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #ifndef DRAGONFLY_H #define DRAGONFLY_H #define DRAGONFLY_MAX_ECC_PRIME_LEN 66 struct crypto_bignum; struct crypto_ec; int dragonfly_suitable_group(int group, int ecc_only); unsigned int dragonfly_min_pwe_loop_iter(int group); int dragonfly_get_random_qr_qnr(const struct crypto_bignum *prime, struct crypto_bignum **qr, struct crypto_bignum **qnr); int dragonfly_is_quadratic_residue_blind(struct crypto_ec *ec, const u8 *qr, const u8 *qnr, const struct crypto_bignum *val); int dragonfly_generate_scalar(const struct crypto_bignum *order, struct crypto_bignum *_rand, struct crypto_bignum *_mask, struct crypto_bignum *scalar); +int dragonfly_sqrt(struct crypto_ec *ec, const struct crypto_bignum *val, + struct crypto_bignum *res); #endif /* DRAGONFLY_H */ diff --git a/contrib/wpa/src/common/qca-vendor.h b/contrib/wpa/src/common/qca-vendor.h index d9eab0212e73..b77e29939195 100644 --- a/contrib/wpa/src/common/qca-vendor.h +++ b/contrib/wpa/src/common/qca-vendor.h @@ -1,11822 +1,11847 @@ /* * Qualcomm Atheros OUI and vendor specific assignments * Copyright (c) 2014-2017, Qualcomm Atheros, Inc. * Copyright (c) 2018-2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #ifndef QCA_VENDOR_H #define QCA_VENDOR_H /* * This file is a registry of identifier assignments from the Qualcomm Atheros * OUI 00:13:74 for purposes other than MAC address assignment. New identifiers * can be assigned through normal review process for changes to the upstream * hostap.git repository. */ #define OUI_QCA 0x001374 #ifndef BIT #define BIT(x) (1U << (x)) #endif /** * enum qca_radiotap_vendor_ids - QCA radiotap vendor namespace IDs */ enum qca_radiotap_vendor_ids { QCA_RADIOTAP_VID_WLANTEST = 0, }; /** * enum qca_nl80211_vendor_subcmds - QCA nl80211 vendor command identifiers * * @QCA_NL80211_VENDOR_SUBCMD_UNSPEC: Reserved value 0 * * @QCA_NL80211_VENDOR_SUBCMD_TEST: Test command/event * * @QCA_NL80211_VENDOR_SUBCMD_ROAMING: Set roaming policy for drivers that use * internal BSS-selection. This command uses * @QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY to specify the new roaming policy * for the current connection (i.e., changes policy set by the nl80211 * Connect command). @QCA_WLAN_VENDOR_ATTR_MAC_ADDR may optionally be * included to indicate which BSS to use in case roaming is disabled. * * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: Recommendation of frequency * ranges to avoid to reduce issues due to interference or internal * co-existence information in the driver. These frequencies aim to * minimize the traffic but not to totally avoid the traffic. That said * for a P2P use case, these frequencies are allowed for the P2P * discovery/negotiation but avoid the group to get formed on these * frequencies. The event data structure is defined in * struct qca_avoid_freq_list. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY: Command to check driver support * for DFS offloading. * * @QCA_NL80211_VENDOR_SUBCMD_NAN: NAN command/event which is used to pass * NAN Request/Response and NAN Indication messages. These messages are * interpreted between the framework and the firmware component. While * sending the command from userspace to the driver, payload is not * encapsulated inside any attribute. Attribute QCA_WLAN_VENDOR_ATTR_NAN * is used when receiving vendor events in userspace from the driver. * * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: Set key operation that can be * used to configure PMK to the driver even when not connected. This can * be used to request offloading of key management operations. Only used * if device supports QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD. * * @QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH: An extended version of * NL80211_CMD_ROAM event with optional attributes including information * from offloaded key management operation. Uses * enum qca_wlan_vendor_attr_roam_auth attributes. Only used * if device supports QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD. * * @QCA_NL80211_VENDOR_SUBCMD_DO_ACS: ACS command/event which is used to * invoke the ACS function in device and pass selected channels to * hostapd. Uses enum qca_wlan_vendor_attr_acs_offload attributes. * * @QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: Command to get the features * supported by the driver. enum qca_wlan_vendor_features defines * the possible features. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED: Event used by driver, * which supports DFS offloading, to indicate a channel availability check * start. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED: Event used by driver, * which supports DFS offloading, to indicate a channel availability check * completion. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED: Event used by driver, * which supports DFS offloading, to indicate that the channel availability * check aborted, no change to the channel status. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED: Event used by * driver, which supports DFS offloading, to indicate that the * Non-Occupancy Period for this channel is over, channel becomes usable. * * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED: Event used by driver, * which supports DFS offloading, to indicate a radar pattern has been * detected. The channel is now unusable. * * @QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO: Get information from the driver. * Attributes defined in enum qca_wlan_vendor_attr_get_wifi_info. * * @QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: Get the feature bitmap * based on enum wifi_logger_supported_features. Attributes defined in * enum qca_wlan_vendor_attr_get_logger_features. * * @QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA: Get the ring data from a particular * logger ring, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID is passed as the * attribute for this command. Attributes defined in * enum qca_wlan_vendor_attr_wifi_logger_start. * * @QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES: Get the supported TDLS * capabilities of the driver, parameters includes the attributes defined * in enum qca_wlan_vendor_attr_tdls_get_capabilities. * * @QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS: Vendor command used to offload * sending of certain periodic IP packet to firmware, attributes defined in * enum qca_wlan_vendor_attr_offloaded_packets. * * @QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI: Command used to configure RSSI * monitoring, defines min and max RSSI which are configured for RSSI * monitoring. Also used to notify the RSSI breach and provides the BSSID * and RSSI value that was breached. Attributes defined in * enum qca_wlan_vendor_attr_rssi_monitoring. * * @QCA_NL80211_VENDOR_SUBCMD_NDP: Command used for performing various NAN * Data Path (NDP) related operations, attributes defined in * enum qca_wlan_vendor_attr_ndp_params. * * @QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD: Command used to enable/disable * Neighbour Discovery offload, attributes defined in * enum qca_wlan_vendor_attr_nd_offload. * * @QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER: Used to set/get the various * configuration parameter for BPF packet filter, attributes defined in * enum qca_wlan_vendor_attr_packet_filter. * * @QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE: Gets the driver-firmware * maximum supported size, attributes defined in * enum qca_wlan_vendor_drv_info. * * @QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS: Command to get various * data about wake reasons and datapath IP statistics, attributes defined * in enum qca_wlan_vendor_attr_wake_stats. * * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG: Command used to set configuration * for IEEE 802.11 communicating outside the context of a basic service * set, called OCB command. Uses the attributes defines in * enum qca_wlan_vendor_attr_ocb_set_config. * * @QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME: Command used to set OCB * UTC time. Use the attributes defines in * enum qca_wlan_vendor_attr_ocb_set_utc_time. * * @QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT: Command used to start * sending OCB timing advert frames. Uses the attributes defines in * enum qca_wlan_vendor_attr_ocb_start_timing_advert. * * @QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT: Command used to stop * OCB timing advert. Uses the attributes defines in * enum qca_wlan_vendor_attr_ocb_stop_timing_advert. * * @QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER: Command used to get TSF * timer value. Uses the attributes defines in * enum qca_wlan_vendor_attr_ocb_get_tsf_resp. * * @QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES: Command/event to update the * link properties of the respective interface. As an event, is used * to notify the connected station's status. The attributes for this * command are defined in enum qca_wlan_vendor_attr_link_properties. * * @QCA_NL80211_VENDOR_SUBCMD_SETBAND: Command to configure the enabled band(s) * to the driver. This command sets the band(s) through either the * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE or * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK (or both). * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE refers enum qca_set_band as unsigned * integer values and QCA_WLAN_VENDOR_ATTR_SETBAND_MASK refers it as 32 * bit unsigned bitmask values. The allowed values for * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE are limited to QCA_SETBAND_AUTO, * QCA_SETBAND_5G, and QCA_SETBAND_2G. Other values/bitmasks are valid for * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. The attribute * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is deprecated and the recommendation * is to use the QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. If the both attributes * are included for backwards compatibility, the configurations through * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK will take the precedence with drivers * that support both attributes. * * @QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY: This command is used to configure * DFS policy and channel hint for ACS operation. This command uses the * attributes defined in enum qca_wlan_vendor_attr_acs_config and * enum qca_acs_dfs_mode. * * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to * start the P2P Listen offload function in device and pass the listen * channel, period, interval, count, device types, and vendor specific * information elements to the device driver and firmware. * Uses the attributes defines in * enum qca_wlan_vendor_attr_p2p_listen_offload. * * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP: Command/event used to * indicate stop request/response of the P2P Listen offload function in * device. As an event, it indicates either the feature stopped after it * was already running or feature has actually failed to start. Uses the * attributes defines in enum qca_wlan_vendor_attr_p2p_listen_offload. * * @QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH: After AP starts * beaconing, this sub command provides the driver, the frequencies on the * 5 GHz band to check for any radar activity. Driver selects one channel * from this priority list provided through * @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST and starts * to check for radar activity on it. If no radar activity is detected * during the channel availability check period, driver internally switches * to the selected frequency of operation. If the frequency is zero, driver * internally selects a channel. The status of this conditional switch is * indicated through an event using the same sub command through * @QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS. Attributes are * listed in qca_wlan_vendor_attr_sap_conditional_chan_switch. * * @QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND: Set GPIO pins. This uses the * attributes defined in enum qca_wlan_gpio_attr. * * @QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY: Fetch hardware capabilities. * This uses @QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY to indicate which * capabilities are to be fetched and other * enum qca_wlan_vendor_attr_get_hw_capability attributes to return the * requested capabilities. * * @QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT: Link layer statistics extension. * enum qca_wlan_vendor_attr_ll_stats_ext attributes are used with this * command and event. * * @QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA: Get capabilities for * indoor location features. Capabilities are reported in * QCA_WLAN_VENDOR_ATTR_LOC_CAPA. * * @QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION: Start an FTM * (fine timing measurement) session with one or more peers. * Specify Session cookie in QCA_WLAN_VENDOR_ATTR_FTM_SESSION_COOKIE and * peer information in QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEERS. * On success, 0 or more QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT * events will be reported, followed by * QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE event to indicate * end of session. * Refer to IEEE P802.11-REVmc/D7.0, 11.24.6 * * @QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION: Abort a running session. * A QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE will be reported with * status code indicating session was aborted. * * @QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT: Event with measurement * results for one peer. Results are reported in * QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEER_RESULTS. * * @QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE: Event triggered when * FTM session is finished, either successfully or aborted by * request. * * @QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER: Configure FTM responder * mode. QCA_WLAN_VENDOR_ATTR_FTM_RESPONDER_ENABLE specifies whether * to enable or disable the responder. LCI/LCR reports can be * configured with QCA_WLAN_VENDOR_ATTR_FTM_LCI and * QCA_WLAN_VENDOR_ATTR_FTM_LCR. Can be called multiple * times to update the LCI/LCR reports. * * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS: Perform a standalone AOA (angle of * arrival) measurement with a single peer. Specify peer MAC address in * QCA_WLAN_VENDOR_ATTR_MAC_ADDR and optionally frequency (MHz) in * QCA_WLAN_VENDOR_ATTR_FREQ (if not specified, locate peer in kernel * scan results cache and use the frequency from there). * Also specify measurement type in QCA_WLAN_VENDOR_ATTR_AOA_TYPE. * Measurement result is reported in * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT event. * * @QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS: Abort an AOA measurement. Specify * peer MAC address in QCA_WLAN_VENDOR_ATTR_MAC_ADDR. * * @QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT: Event that reports * the AOA measurement result. * Peer MAC address reported in QCA_WLAN_VENDOR_ATTR_MAC_ADDR. * success/failure status is reported in * QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS. * Measurement data is reported in QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT. * The antenna array(s) used in the measurement are reported in * QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK. * * @QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST: Encrypt/decrypt the given * data as per the given parameters. * * @QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI: Get antenna RSSI value for a * specific chain. * * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG: Get low level * configuration for a DMG RF sector. Specify sector index in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX, sector type in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and RF modules * to return sector information for in * QCA_WLAN_VENDOR_ATTR_DMG_RF_MODULE_MASK. Returns sector configuration * in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG. Also return the * exact time where information was captured in * QCA_WLAN_VENDOR_ATTR_TSF. * * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG: Set low level * configuration for a DMG RF sector. Specify sector index in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX, sector type in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and sector configuration * for one or more DMG RF modules in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG. * * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR: Get selected * DMG RF sector for a station. This is the sector that the HW * will use to communicate with the station. Specify the MAC address * of associated station/AP/PCP in QCA_WLAN_VENDOR_ATTR_MAC_ADDR (not * needed for unassociated station). Specify sector type to return in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE. Returns the selected * sector index in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX. * Also return the exact time where the information was captured * in QCA_WLAN_VENDOR_ATTR_TSF. * * @QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR: Set the * selected DMG RF sector for a station. This is the sector that * the HW will use to communicate with the station. * Specify the MAC address of associated station/AP/PCP in * QCA_WLAN_VENDOR_ATTR_MAC_ADDR, the sector type to select in * QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE and the sector index * in QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX. * The selected sector will be locked such that it will not be * modified like it normally does (for example when station * moves around). To unlock the selected sector for a station * pass the special value 0xFFFF in the sector index. To unlock * all connected stations also pass a broadcast MAC address. * * @QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS: Configure the TDLS behavior * in the host driver. The different TDLS configurations are defined * by the attributes in enum qca_wlan_vendor_attr_tdls_configuration. * * @QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES: Query device IEEE 802.11ax HE * capabilities. The response uses the attributes defined in * enum qca_wlan_vendor_attr_get_he_capabilities. * * @QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN: Abort an ongoing vendor scan that was * started with QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN. This command * carries the scan cookie of the corresponding scan request. The scan * cookie is represented by QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE. * * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS: Set the Specific * Absorption Rate (SAR) power limits. A critical regulation for * FCC compliance, OEMs require methods to set SAR limits on TX * power of WLAN/WWAN. enum qca_vendor_attr_sar_limits * attributes are used with this command. * * @QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS: This command/event is used by the * host driver for offloading the implementation of Auto Channel Selection * (ACS) to an external user space entity. This interface is used as the * event from the host driver to the user space entity and also as the * request from the user space entity to the host driver. The event from * the host driver is used by the user space entity as an indication to * start the ACS functionality. The attributes used by this event are * represented by the enum qca_wlan_vendor_attr_external_acs_event. * User space entity uses the same interface to inform the host driver with * selected channels after the ACS operation using the attributes defined * by enum qca_wlan_vendor_attr_external_acs_channels. * * @QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE: Vendor event carrying the * requisite information leading to a power save failure. The information * carried as part of this event is represented by the * enum qca_attr_chip_power_save_failure attributes. * * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET: Start/Stop the NUD statistics * collection. Uses attributes defined in enum qca_attr_nud_stats_set. * * @QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET: Get the NUD statistics. These * statistics are represented by the enum qca_attr_nud_stats_get * attributes. * * @QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS: Sub-command to fetch * the BSS transition status, whether accept or reject, for a list of * candidate BSSIDs provided by the userspace. This uses the vendor * attributes QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON and * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO. The userspace shall specify * the attributes QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON and an * array of QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID nested in * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO in the request. In the response * the driver shall specify array of * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID and * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS pairs nested in * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO. * * @QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL: Set the trace level for a * specific QCA module. The trace levels are represented by * enum qca_attr_trace_level attributes. * * @QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT: Set the Beam Refinement * Protocol antenna limit in different modes. See enum * qca_wlan_vendor_attr_brp_ant_limit_mode. * * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START: Start spectral scan. The scan * parameters are specified by enum qca_wlan_vendor_attr_spectral_scan. * This returns a cookie (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE) * identifying the operation in success case. In failure cases an * error code (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE) * describing the reason for the failure is returned. * * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP: Stop spectral scan. This uses * a cookie (%QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE) from * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START to identify the scan to * be stopped. * * @QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS: Set the active Type Of Service on the * specific interface. This can be used to modify some of the low level * scan parameters (off channel dwell time, home channel time) in the * driver/firmware. These parameters are maintained within the host driver. * This command is valid only when the interface is in the connected state. * These scan parameters shall be reset by the driver/firmware once * disconnected. The attributes used with this command are defined in * enum qca_wlan_vendor_attr_active_tos. * * @QCA_NL80211_VENDOR_SUBCMD_HANG: Event indicating to the user space that the * driver has detected an internal failure. This event carries the * information indicating the reason that triggered this detection. The * attributes for this command are defined in * enum qca_wlan_vendor_attr_hang. * * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG: Get the current values * of spectral parameters used. The spectral scan parameters are specified * by enum qca_wlan_vendor_attr_spectral_scan. * * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS: Get the debug stats * for spectral scan functionality. The debug stats are specified by * enum qca_wlan_vendor_attr_spectral_diag_stats. * * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO: Get spectral * scan system capabilities. The capabilities are specified * by enum qca_wlan_vendor_attr_spectral_cap. * * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS: Get the current * status of spectral scan. The status values are specified * by enum qca_wlan_vendor_attr_spectral_scan_status. * * @QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING: Sub-command to flush * peer pending packets. Specify the peer MAC address in * QCA_WLAN_VENDOR_ATTR_PEER_ADDR and the access category of the packets * in QCA_WLAN_VENDOR_ATTR_AC. The attributes are listed * in enum qca_wlan_vendor_attr_flush_pending. * * @QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO: Get vendor specific Representative * RF Operating Parameter (RROP) information. The attributes for this * information are defined in enum qca_wlan_vendor_attr_rrop_info. This is * intended for use by external Auto Channel Selection applications. * * @QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS: Get the Specific Absorption Rate * (SAR) power limits. This is a companion to the command * @QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS and is used to retrieve the * settings currently in use. The attributes returned by this command are * defined by enum qca_vendor_attr_sar_limits. * * @QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO: Provides the current behavior of * the WLAN hardware MAC. Also, provides the WLAN netdev interface * information attached to the respective MAC. * This works both as a query (user space asks the current mode) or event * interface (driver advertising the current mode to the user space). * Driver does not trigger this event for temporary hardware mode changes. * Mode changes w.r.t Wi-Fi connection update (VIZ creation / deletion, * channel change, etc.) are updated with this event. Attributes for this * interface are defined in enum qca_wlan_vendor_attr_mac. * * @QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH: Set MSDU queue depth threshold * per peer per TID. Attributes for this command are define in * enum qca_wlan_set_qdepth_thresh_attr. * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD: Provides the thermal shutdown action * guide for WLAN driver. Request to suspend of driver and FW if the * temperature is higher than the suspend threshold; resume action is * requested to driver if the temperature is lower than the resume * threshold. In user poll mode, request temperature data by user. For test * purpose, getting thermal shutdown configuration parameters is needed. * Attributes for this interface are defined in * enum qca_wlan_vendor_attr_thermal_cmd. * @QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT: Thermal events reported from * driver. Thermal temperature and indication of resume completion are * reported as thermal events. The attributes for this command are defined * in enum qca_wlan_vendor_attr_thermal_event. * * @QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION: Sub command to set WiFi * test configuration. Attributes for this command are defined in * enum qca_wlan_vendor_attr_wifi_test_config. * * @QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER: This command is used to configure an * RX filter to receive frames from stations that are active on the * operating channel, but not associated with the local device (e.g., STAs * associated with other APs). Filtering is done based on a list of BSSIDs * and STA MAC addresses added by the user. This command is also used to * fetch the statistics of unassociated stations. The attributes used with * this command are defined in enum qca_wlan_vendor_attr_bss_filter. * * @QCA_NL80211_VENDOR_SUBCMD_NAN_EXT: An extendable version of NAN vendor * command. The earlier command for NAN, QCA_NL80211_VENDOR_SUBCMD_NAN, * carried a payload which was a binary blob of data. The command was not * extendable to send more information. The newer version carries the * legacy blob encapsulated within an attribute and can be extended with * additional vendor attributes that can enhance the NAN command interface. * @QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT: Event to indicate scan triggered * or stopped within driver/firmware in order to initiate roaming. The * attributes used with this event are defined in enum * qca_wlan_vendor_attr_roam_scan. Some drivers may not send these events * in few cases, e.g., if the host processor is sleeping when this event * is generated in firmware. * * @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to * configure parameters per peer to capture Channel Frequency Response * (CFR) and enable Periodic CFR capture. The attributes for this command * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr. This command * can also be used to send CFR data from the driver to userspace when * netlink events are used to send CFR data. * * @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes * in throughput dynamically. The driver estimates the throughput based on * number of packets being transmitted/received per second and indicates * the changes in throughput to user space. Userspace tools can use this * information to configure kernel's TCP parameters in order to achieve * peak throughput. Optionally, the driver will also send guidance on * modifications to kernel's TCP parameters which can be referred by * userspace tools. The attributes used with this event are defined in enum * qca_wlan_vendor_attr_throughput_change. * * @QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG: This command is used to set * priorities among different types of traffic during coex scenarios. * Current supported prioritization is among WLAN/BT/ZIGBEE with different * profiles mentioned in enum qca_coex_config_profiles. The associated * attributes used with this command are defined in enum * qca_vendor_attr_coex_config. * * Based on the config provided, FW will boost the weight and prioritize * the traffic for that subsystem (WLAN/BT/Zigbee). * * @QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS: This command is used to query * the supported AKM suite selectorss from the driver. It returns the list * of supported AKMs in the attribute NL80211_ATTR_AKM_SUITES. * @QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE: This command is used to get firmware * state from the driver. It returns the firmware state in the attribute * QCA_WLAN_VENDOR_ATTR_FW_STATE. * @QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH: This vendor subcommand * is used by the driver to flush per-peer cached statistics to user space * application. This interface is used as an event from the driver to * user space application. Attributes for this event are specified in * enum qca_wlan_vendor_attr_peer_stats_cache_params. * QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA attribute is expected to be * sent in the event. * @QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG: This sub command is used to * improve the success rate of Zigbee joining network. * Due to PTA master limitation, Zigbee joining network success rate is * low while WLAN is working. The WLAN driver needs to configure some * parameters including Zigbee state and specific WLAN periods to enhance * PTA master. All these parameters are delivered by the attributes * defined in enum qca_mpta_helper_vendor_attr. * @QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING: This sub command is used to * implement Beacon frame reporting feature. * * Userspace can request the driver/firmware to periodically report * received Beacon frames whose BSSID is same as the current connected * BSS's MAC address. * * In case the STA seamlessly (without sending disconnect indication to * userspace) roams to a different BSS, Beacon frame reporting will be * automatically enabled for the Beacon frames whose BSSID is same as the * MAC address of the new BSS. Beacon reporting will be stopped when the * STA is disconnected (when the disconnect indication is sent to * userspace) and need to be explicitly enabled by userspace for next * connection. * * When a Beacon frame matching configured conditions is received, and if * userspace has requested to send asynchronous beacon reports, the * driver/firmware will encapsulate the details of the Beacon frame in an * event and send it to userspace along with updating the BSS information * in cfg80211 scan cache, otherwise driver will only update the cfg80211 * scan cache with the information from the received Beacon frame but will * not send any active report to userspace. * * The userspace can request the driver/firmware to stop reporting Beacon * frames. If the driver/firmware is not able to receive Beacon frames due * to other Wi-Fi operations such as off-channel activities, etc., the * driver/firmware will send a pause event to userspace and stop reporting * Beacon frames. Whether the beacon reporting will be automatically * resumed or not by the driver/firmware later will be reported to * userspace using the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES * flag. The beacon reporting shall be resumed for all the cases except * either when userspace sets * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME flag in the command * which triggered the current beacon reporting or during any disconnection * case as indicated by setting * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON to * QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_DISCONNECTED by the * driver. * * After QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_PAUSE event is received * by userspace with QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES * flag not set, the next first * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO event from the driver * shall be considered as un-pause event. * * All the attributes used with this command are defined in * enum qca_wlan_vendor_attr_beacon_reporting_params. * @QCA_NL80211_VENDOR_SUBCMD_INTEROP_ISSUES_AP: In practice, some APs have * interop issues with the DUT. This sub command is used to transfer the * AP info between the driver and user space. This works both as a command * and an event. As a command, it configures the stored list of APs from * user space to firmware; as an event, it indicates the AP info detected * by the firmware to user space for persistent storage. The attributes * defined in enum qca_vendor_attr_interop_issues_ap are used to deliver * the parameters. * @QCA_NL80211_VENDOR_SUBCMD_OEM_DATA: This command/event is used to * send/receive OEM data binary blobs to/from application/service to/from * firmware. The attributes defined in enum * qca_wlan_vendor_attr_oem_data_params are used to deliver the * parameters. * @QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT: This command/event is used * to send/receive avoid frequency data using * enum qca_wlan_vendor_attr_avoid_frequency_ext. * This new command is alternative to existing command * QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY since existing command/event * is using stream of bytes instead of structured data using vendor * attributes. User space sends unsafe frequency ranges to the driver using * a nested attribute %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE. On * reception of this command, the driver shall check if an interface is * operating on an unsafe frequency and the driver shall try to move to a * safe channel when needed. If the driver is not able to find a safe * channel the interface can keep operating on an unsafe channel with the * TX power limit derived based on internal configurations like * regulatory/SAR rules. * * @QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: This vendor subcommand is used to * add the STA node details in driver/firmware. Attributes for this event * are specified in enum qca_wlan_vendor_attr_add_sta_node_params. * @QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE: This command is used to set BT * coex chain mode from application/service. * The attributes defined in enum qca_vendor_attr_btc_chain_mode are used * to deliver the parameters. * * @QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO: This vendor subcommand is used to * get information of a station from driver to userspace. This command can * be used in both STA and AP modes. For STA mode, it provides information * of the current association when in connected state or the last * association when in disconnected state. For AP mode, only information * of the currently connected stations is available. This command uses * attributes defined in enum qca_wlan_vendor_attr_get_sta_info. * * @QCA_NL80211_VENDOR_SUBCMD_REQUEST_SAR_LIMITS_EVENT: This acts as an event. * Host drivers can request the user space entity to set the SAR power * limits with this event. Accordingly, the user space entity is expected * to set the SAR power limits. Host drivers can retry this event to the * user space for the SAR power limits configuration from user space. If * the driver does not get the SAR power limits from user space for all * the retried attempts, it can configure a default SAR power limit. * * @QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO: This acts as a vendor event and * is used to update the information about the station from the driver to * userspace. Uses attributes from enum * qca_wlan_vendor_attr_update_sta_info. * * @QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON: This acts as an event. * The host driver initiates the disconnection for scenarios such as beacon * miss, NUD failure, peer kick out, etc. The disconnection indication * through cfg80211_disconnected() expects the reason codes from enum * ieee80211_reasoncode which does not signify these various reasons why * the driver has triggered the disconnection. This event will be used to * send the driver specific reason codes by the host driver to userspace. * Host drivers should trigger this event and pass the respective reason * code immediately prior to triggering cfg80211_disconnected(). The * attributes used with this event are defined in enum * qca_wlan_vendor_attr_driver_disconnect_reason. * * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC: This vendor subcommand is used to * add/delete TSPEC for each AC. One command is for one specific AC only. * This command can only be used in STA mode and the STA must be * associated with an AP when the command is issued. Uses attributes * defined in enum qca_wlan_vendor_attr_config_tspec. * * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT. * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt. * * @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from * the driver. The band configurations obtained are referred through * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. * * @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium * assessment. * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess. * * @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is * used to update SSID information in hostapd when it is updated in the * driver. Uses the attribute NL80211_ATTR_SSID. * * @QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS: This vendor subcommand is used by * the driver to send opaque data from the firmware to userspace. The * driver sends an event to userspace whenever such data is received from * the firmware. * * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to * send this opaque data for this event. * * The format of the opaque data is specific to the particular firmware * version and there is no guarantee of the format remaining same. * * @QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS: This acts as an event. * The host driver selects Tx VDEV, and notifies user. The attributes * used with this event are defined in enum * qca_wlan_vendor_attr_mbssid_tx_vdev_status. * This event contains Tx VDEV group information, other VDEVs * interface index, and status information. * * @QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY: Vendor command to * configure the concurrent session policies when multiple STA interfaces * are (getting) active. The attributes used by this command are defined * in enum qca_wlan_vendor_attr_concurrent_sta_policy. * * @QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS: Userspace can use this command * to query usable channels for different interface types such as STA, * AP, P2P GO, P2P Client, NAN, etc. The driver shall report all usable * channels in the response based on country code, different static * configurations, concurrency combinations, etc. The attributes used * with this command are defined in * enum qca_wlan_vendor_attr_usable_channels. * * @QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY: This vendor subcommand is used * to get DFS radar history from the driver to userspace. The driver * returns QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES attribute with an * array of nested entries. * * @QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD: Userspace can use this command to * enable/disable mDNS offload to the firmware. The attributes used with * this command are defined in enum qca_wlan_vendor_attr_mdns_offload. * * @QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE: This vendor subcommand is used * to set packet monitor mode that aims to send the specified set of TX and * RX frames on the current client interface to an active monitor * interface. If this monitor mode is set, the driver will send the * configured frames, from the interface on which the command is issued, to * an active monitor interface. The attributes used with this command are * defined in enum qca_wlan_vendor_attr_set_monitor_mode. * * Though the monitor mode is configured for the respective * Data/Management/Control frames, it is up to the respective WLAN * driver/firmware/hardware designs to consider the possibility of sending * these frames over the monitor interface. For example, the Control frames * are handled within the hardware and thus passing such frames over the * monitor interface is left to the respective designs. * * Also, this monitor mode is governed to behave accordingly in * suspend/resume states. If the firmware handles any of such frames in * suspend state without waking up the host and if the monitor mode is * configured to notify all such frames, the firmware is expected to resume * the host and forward the respective frames to the monitor interface. * Please note that such a request to get the frames over the monitor * interface will have a definite power implication. * * @QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS: This vendor subcommand is used both * as a request to set the driver/firmware with the parameters to trigger * the roaming events, and also used by the driver/firmware to pass on the * various roam events to userspace. * Applicable only for the STA mode. The attributes used with this command * are defined in enum qca_wlan_vendor_attr_roam_events. */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, QCA_NL80211_VENDOR_SUBCMD_TEST = 1, /* subcmds 2..8 not yet allocated */ QCA_NL80211_VENDOR_SUBCMD_ROAMING = 9, QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY = 10, QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY = 11, QCA_NL80211_VENDOR_SUBCMD_NAN = 12, QCA_NL80211_VENDOR_SUBCMD_STATS_EXT = 13, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET = 14, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET = 15, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR = 16, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS = 17, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS = 18, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS = 19, QCA_NL80211_VENDOR_SUBCMD_GSCAN_START = 20, QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP = 21, QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS = 22, QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES = 23, QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS = 24, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE = 25, QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT = 26, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT = 27, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND = 28, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST = 29, QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST = 30, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE = 31, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE = 32, QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE = 33, QCA_NL80211_VENDOR_SUBCMD_TDLS_ENABLE = 34, QCA_NL80211_VENDOR_SUBCMD_TDLS_DISABLE = 35, QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_STATUS = 36, QCA_NL80211_VENDOR_SUBCMD_TDLS_STATE = 37, QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES = 38, QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI = 39, QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG = 40, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST = 41, QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX = 42, /* 43..49 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY = 50, QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH = 51, QCA_NL80211_VENDOR_SUBCMD_APFIND = 52, /* 53 - reserved - was used by QCA, but not in use anymore */ QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54, QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES = 55, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED = 56, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_FINISHED = 57, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_ABORTED = 58, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_NOP_FINISHED = 59, QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60, QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO = 61, QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START = 62, QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP = 63, QCA_NL80211_VENDOR_SUBCMD_ROAM = 64, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST = 65, QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SSID_HOTLIST = 66, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND = 67, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST = 68, QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST = 69, QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST = 70, QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST = 71, QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND = 72, QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND = 73, /* Wi-Fi configuration subcommands */ QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION = 74, QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION = 75, QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET = 76, QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA = 77, QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES = 78, QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS = 79, QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80, QCA_NL80211_VENDOR_SUBCMD_NDP = 81, QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD = 82, QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83, QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE = 84, QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS = 85, /* 86-90 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91, QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92, QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93, QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT = 94, QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT = 95, QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER = 96, QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS = 97, QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS = 98, QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL = 99, QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT = 100, QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101, QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102, QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103, QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104, QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105, QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN = 106, QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE = 107, QCA_NL80211_VENDOR_SUBCMD_OTA_TEST = 108, QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_SCALE = 109, /* 110..114 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_DECR_DB = 115, QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY = 116, /* 117 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_SET_SAP_CONFIG = 118, QCA_NL80211_VENDOR_SUBCMD_TSF = 119, QCA_NL80211_VENDOR_SUBCMD_WISA = 120, /* 121 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START = 122, QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP = 123, QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH = 124, QCA_NL80211_VENDOR_SUBCMD_GPIO_CONFIG_COMMAND = 125, QCA_NL80211_VENDOR_SUBCMD_GET_HW_CAPABILITY = 126, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_EXT = 127, /* FTM/indoor location subcommands */ QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA = 128, QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION = 129, QCA_NL80211_VENDOR_SUBCMD_FTM_ABORT_SESSION = 130, QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT = 131, QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE = 132, QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER = 133, QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS = 134, QCA_NL80211_VENDOR_SUBCMD_AOA_ABORT_MEAS = 135, QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT = 136, QCA_NL80211_VENDOR_SUBCMD_ENCRYPTION_TEST = 137, QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI = 138, /* DMG low level RF sector operations */ QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG = 139, QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG = 140, QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SELECTED_SECTOR = 141, QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR = 142, QCA_NL80211_VENDOR_SUBCMD_CONFIGURE_TDLS = 143, QCA_NL80211_VENDOR_SUBCMD_GET_HE_CAPABILITIES = 144, QCA_NL80211_VENDOR_SUBCMD_ABORT_SCAN = 145, QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS = 146, QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS = 147, QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE = 148, QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET = 149, QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET = 150, QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS = 151, QCA_NL80211_VENDOR_SUBCMD_SET_TRACE_LEVEL = 152, QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT = 153, QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START = 154, QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP = 155, QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS = 156, QCA_NL80211_VENDOR_SUBCMD_HANG = 157, QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CONFIG = 158, QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS = 159, QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO = 160, QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS = 161, /* Flush peer pending data */ QCA_NL80211_VENDOR_SUBCMD_PEER_FLUSH_PENDING = 162, QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO = 163, QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS = 164, QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO = 165, QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH = 166, /* Thermal shutdown commands to protect wifi chip */ QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD = 167, QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT = 168, /* Wi-Fi test configuration subcommand */ QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION = 169, /* Frame filter operations for other BSSs/unassociated STAs */ QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER = 170, QCA_NL80211_VENDOR_SUBCMD_NAN_EXT = 171, QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT = 172, QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG = 173, QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT = 174, QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG = 175, QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS = 176, QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE = 177, QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH = 178, QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG = 179, QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING = 180, QCA_NL80211_VENDOR_SUBCMD_INTEROP_ISSUES_AP = 181, QCA_NL80211_VENDOR_SUBCMD_OEM_DATA = 182, QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT = 183, QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE = 184, QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE = 185, QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO = 186, QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT = 187, QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO = 188, QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON = 189, QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC = 190, QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193, QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194, QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195, QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196, QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY = 197, QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS = 198, QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY = 199, QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD = 200, /* 201 - reserved for QCA */ QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE = 202, QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS = 203, }; enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_INVALID = 0, /* used by QCA_NL80211_VENDOR_SUBCMD_DFS_CAPABILITY */ QCA_WLAN_VENDOR_ATTR_DFS = 1, /* Used only when driver sends vendor events to the userspace under the * command QCA_NL80211_VENDOR_SUBCMD_NAN. Not used when userspace sends * commands to the driver. */ QCA_WLAN_VENDOR_ATTR_NAN = 2, /* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */ QCA_WLAN_VENDOR_ATTR_STATS_EXT = 3, /* used by QCA_NL80211_VENDOR_SUBCMD_STATS_EXT */ QCA_WLAN_VENDOR_ATTR_IFINDEX = 4, /* used by QCA_NL80211_VENDOR_SUBCMD_ROAMING, u32 with values defined * by enum qca_roaming_policy. */ QCA_WLAN_VENDOR_ATTR_ROAMING_POLICY = 5, QCA_WLAN_VENDOR_ATTR_MAC_ADDR = 6, /* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */ QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7, QCA_WLAN_VENDOR_ATTR_TEST = 8, /* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */ /* Unsigned 32-bit value. */ QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA = 9, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11, /* Unsigned 32-bit value from enum qca_set_band. The allowed values for * this attribute are limited to QCA_SETBAND_AUTO, QCA_SETBAND_5G, and * QCA_SETBAND_2G. This attribute is deprecated. Recommendation is to * use QCA_WLAN_VENDOR_ATTR_SETBAND_MASK instead. */ QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12, /* Dummy (NOP) attribute for 64 bit padding */ QCA_WLAN_VENDOR_ATTR_PAD = 13, /* Unique FTM session cookie (Unsigned 64 bit). Specified in * QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION. Reported in * the session in QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT and * QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE. */ QCA_WLAN_VENDOR_ATTR_FTM_SESSION_COOKIE = 14, /* Indoor location capabilities, returned by * QCA_NL80211_VENDOR_SUBCMD_LOC_GET_CAPA. * see enum qca_wlan_vendor_attr_loc_capa. */ QCA_WLAN_VENDOR_ATTR_LOC_CAPA = 15, /* Array of nested attributes containing information about each peer * in FTM measurement session. See enum qca_wlan_vendor_attr_peer_info * for supported attributes for each peer. */ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEERS = 16, /* Array of nested attributes containing measurement results for * one or more peers, reported by the * QCA_NL80211_VENDOR_SUBCMD_FTM_MEAS_RESULT event. * See enum qca_wlan_vendor_attr_peer_result for list of supported * attributes. */ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PEER_RESULTS = 17, /* Flag attribute for enabling or disabling responder functionality. */ QCA_WLAN_VENDOR_ATTR_FTM_RESPONDER_ENABLE = 18, /* Used in the QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER * command to specify the LCI report that will be sent by * the responder during a measurement exchange. The format is * defined in IEEE P802.11-REVmc/D7.0, 9.4.2.22.10. */ QCA_WLAN_VENDOR_ATTR_FTM_LCI = 19, /* Used in the QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER * command to specify the location civic report that will * be sent by the responder during a measurement exchange. * The format is defined in IEEE P802.11-REVmc/D7.0, 9.4.2.22.13. */ QCA_WLAN_VENDOR_ATTR_FTM_LCR = 20, /* Session/measurement completion status code, * reported in QCA_NL80211_VENDOR_SUBCMD_FTM_SESSION_DONE and * QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT * see enum qca_vendor_attr_loc_session_status. */ QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS = 21, /* Initial dialog token used by responder (0 if not specified), * unsigned 8 bit value. */ QCA_WLAN_VENDOR_ATTR_FTM_INITIAL_TOKEN = 22, /* AOA measurement type. Requested in QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS * and optionally in QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION if * AOA measurements are needed as part of an FTM session. * Reported by QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS_RESULT. See * enum qca_wlan_vendor_attr_aoa_type. */ QCA_WLAN_VENDOR_ATTR_AOA_TYPE = 23, /* A bit mask (unsigned 32 bit value) of antenna arrays used * by indoor location measurements. Refers to the antenna * arrays described by QCA_VENDOR_ATTR_LOC_CAPA_ANTENNA_ARRAYS. */ QCA_WLAN_VENDOR_ATTR_LOC_ANTENNA_ARRAY_MASK = 24, /* AOA measurement data. Its contents depends on the AOA measurement * type and antenna array mask: * QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE: array of U16 values, * phase of the strongest CIR path for each antenna in the measured * array(s). * QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP: array of 2 U16 * values, phase and amplitude of the strongest CIR path for each * antenna in the measured array(s). */ QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT = 25, /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command * to specify the chain number (unsigned 32 bit value) to inquire * the corresponding antenna RSSI value */ QCA_WLAN_VENDOR_ATTR_CHAIN_INDEX = 26, /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command * to report the specific antenna RSSI value (unsigned 32 bit value) */ QCA_WLAN_VENDOR_ATTR_CHAIN_RSSI = 27, /* Frequency in MHz, various uses. Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_FREQ = 28, /* TSF timer value, unsigned 64 bit value. * May be returned by various commands. */ QCA_WLAN_VENDOR_ATTR_TSF = 29, /* DMG RF sector index, unsigned 16 bit number. Valid values are * 0..127 for sector indices or 65535 as special value used to * unlock sector selection in * QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SELECTED_SECTOR. */ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_INDEX = 30, /* DMG RF sector type, unsigned 8 bit value. One of the values * in enum qca_wlan_vendor_attr_dmg_rf_sector_type. */ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE = 31, /* Bitmask of DMG RF modules for which information is requested. Each * bit corresponds to an RF module with the same index as the bit * number. Unsigned 32 bit number but only low 8 bits can be set since * all DMG chips currently have up to 8 RF modules. */ QCA_WLAN_VENDOR_ATTR_DMG_RF_MODULE_MASK = 32, /* Array of nested attributes where each entry is DMG RF sector * configuration for a single RF module. * Attributes for each entry are taken from enum * qca_wlan_vendor_attr_dmg_rf_sector_cfg. * Specified in QCA_NL80211_VENDOR_SUBCMD_DMG_RF_SET_SECTOR_CFG * and returned by QCA_NL80211_VENDOR_SUBCMD_DMG_RF_GET_SECTOR_CFG. */ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG = 33, /* Used in QCA_NL80211_VENDOR_SUBCMD_STATS_EXT command * to report frame aggregation statistics to userspace. */ QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_NUM = 34, QCA_WLAN_VENDOR_ATTR_RX_AGGREGATION_STATS_HOLES_INFO = 35, /* Unsigned 8-bit value representing MBO transition reason code as * provided by the AP used by subcommand * QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS. This is * specified by the userspace in the request to the driver. */ QCA_WLAN_VENDOR_ATTR_BTM_MBO_TRANSITION_REASON = 36, /* Array of nested attributes, BSSID and status code, used by subcommand * QCA_NL80211_VENDOR_SUBCMD_FETCH_BSS_TRANSITION_STATUS, where each * entry is taken from enum qca_wlan_vendor_attr_btm_candidate_info. * The userspace space specifies the list/array of candidate BSSIDs in * the order of preference in the request. The driver specifies the * status code, for each BSSID in the list, in the response. The * acceptable candidates are listed in the order preferred by the * driver. */ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO = 37, /* Used in QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT command * See enum qca_wlan_vendor_attr_brp_ant_limit_mode. */ QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE = 38, /* Used in QCA_NL80211_VENDOR_SUBCMD_BRP_SET_ANT_LIMIT command * to define the number of antennas to use for BRP. * different purpose in each ANT_LIMIT_MODE: * DISABLE - ignored * EFFECTIVE - upper limit to number of antennas to be used * FORCE - exact number of antennas to be used * unsigned 8 bit value */ QCA_WLAN_VENDOR_ATTR_BRP_ANT_NUM_LIMIT = 39, /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command * to report the corresponding antenna index to the chain RSSI value */ QCA_WLAN_VENDOR_ATTR_ANTENNA_INFO = 40, /* Used in QCA_NL80211_VENDOR_SUBCMD_GET_CHAIN_RSSI command to report * the specific antenna EVM value (unsigned 32 bit value). With a * determinate group of antennas, the driver specifies the EVM value * for each antenna ID, and application extract them in user space. */ QCA_WLAN_VENDOR_ATTR_CHAIN_EVM = 41, /* * Used in QCA_NL80211_VENDOR_SUBCMD_GET_FW_STATE command to report * wlan firmware current state. FW state is an unsigned 8 bit value, * one of the values in enum qca_wlan_vendor_attr_fw_state. */ QCA_WLAN_VENDOR_ATTR_FW_STATE = 42, /* Unsigned 32-bitmask value from enum qca_set_band. Substitutes the * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE for which only a subset * of single values from enum qca_set_band are valid. This attribute * uses bitmask combinations to define the respective allowed band * combinations and this attributes takes precedence over * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE if both attributes are included. */ QCA_WLAN_VENDOR_ATTR_SETBAND_MASK = 43, /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1, }; enum qca_roaming_policy { QCA_ROAMING_NOT_ALLOWED, QCA_ROAMING_ALLOWED_WITHIN_ESS, }; /** * enum qca_roam_reason - Represents the reason codes for roaming. Used by * QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON. * * @QCA_ROAM_REASON_UNKNOWN: Any reason that do not classify under the below * reasons. * * @QCA_ROAM_REASON_PER: Roam triggered when packet error rates (PER) breached * the configured threshold. * * @QCA_ROAM_REASON_BEACON_MISS: Roam triggered due to the continuous configured * beacon misses from the then connected AP. * * @QCA_ROAM_REASON_POOR_RSSI: Roam triggered due to the poor RSSI reported * by the connected AP. * * @QCA_ROAM_REASON_BETTER_RSSI: Roam triggered for finding a BSS with a better * RSSI than the connected BSS. Here the RSSI of the current BSS is not poor. * * @QCA_ROAM_REASON_CONGESTION: Roam triggered considering the connected channel * or environment being very noisy or congested. * * @QCA_ROAM_REASON_USER_TRIGGER: Roam triggered due to an explicit request * from the user (user space). * * @QCA_ROAM_REASON_BTM: Roam triggered due to BTM Request frame received from * the connected AP. * * @QCA_ROAM_REASON_BSS_LOAD: Roam triggered due to the channel utilization * breaching out the configured threshold. * * @QCA_ROAM_REASON_WTC: Roam triggered due to Wireless to Cellular BSS * transition request. * * @QCA_ROAM_REASON_IDLE: Roam triggered when device is suspended, there is no * data activity with the AP and the current RSSI falls below a certain * threshold. * * @QCA_ROAM_REASON_DISCONNECTION: Roam triggered due to Deauthentication or * Disassociation frames received from the connected AP. * * @QCA_ROAM_REASON_PERIODIC_TIMER: Roam triggered as part of the periodic scan * that happens when there is no candidate AP found during the poor RSSI scan * trigger. * * @QCA_ROAM_REASON_BACKGROUND_SCAN: Roam triggered based on the scan results * obtained from an external scan (not aimed at roaming). * * @QCA_ROAM_REASON_BT_ACTIVITY: Roam triggered due to Bluetooth connection is * established when the station is connected in the 2.4 GHz band. */ enum qca_roam_reason { QCA_ROAM_REASON_UNKNOWN, QCA_ROAM_REASON_PER, QCA_ROAM_REASON_BEACON_MISS, QCA_ROAM_REASON_POOR_RSSI, QCA_ROAM_REASON_BETTER_RSSI, QCA_ROAM_REASON_CONGESTION, QCA_ROAM_REASON_USER_TRIGGER, QCA_ROAM_REASON_BTM, QCA_ROAM_REASON_BSS_LOAD, QCA_ROAM_REASON_WTC, QCA_ROAM_REASON_IDLE, QCA_ROAM_REASON_DISCONNECTION, QCA_ROAM_REASON_PERIODIC_TIMER, QCA_ROAM_REASON_BACKGROUND_SCAN, QCA_ROAM_REASON_BT_ACTIVITY, }; enum qca_wlan_vendor_attr_roam_auth { QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS, /* Indicates the status of re-association requested by user space for * the BSSID specified by QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID. * Type u16. * Represents the status code from AP. Use * %WLAN_STATUS_UNSPECIFIED_FAILURE if the device cannot give you the * real status code for failures. */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS, /* This attribute indicates that the old association was maintained when * a re-association is requested by user space and that re-association * attempt fails (i.e., cannot connect to the requested BSS, but can * remain associated with the BSS with which the association was in * place when being requested to roam). Used along with * WLAN_VENDOR_ATTR_ROAM_AUTH_STATUS to indicate the current * re-association status. Type flag. * This attribute is applicable only for re-association failure cases. */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RETAIN_CONNECTION, /* This attribute specifies the PMK if one was newly generated during * FILS roaming. This is added to the PMKSA cache and is used in * subsequent connections with PMKSA caching. */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK = 11, /* This attribute specifies the PMKID used/generated for the current * FILS roam. This is used in subsequent connections with PMKSA caching. */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID = 12, /* A 16-bit unsigned value specifying the next sequence number to use * in ERP message in the currently associated realm. This is used in * doing subsequent ERP based connections in the same realm. */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM = 13, /* A 16-bit unsigned value representing the reasons for the roaming. * Defined by enum qca_roam_reason. */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON = 14, /* keep last */ QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_MAX = QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1 }; enum qca_wlan_vendor_attr_p2p_listen_offload { QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INVALID = 0, /* A 32-bit unsigned value; the P2P listen frequency (MHz); must be one * of the social channels. */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL, /* A 32-bit unsigned value; the P2P listen offload period (ms). */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD, /* A 32-bit unsigned value; the P2P listen interval duration (ms). */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL, /* A 32-bit unsigned value; number of interval times the firmware needs * to run the offloaded P2P listen operation before it stops. */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT, /* An array of arbitrary binary data with one or more 8-byte values. * The device types include both primary and secondary device types. */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES, /* An array of unsigned 8-bit characters; vendor information elements. */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE, /* A 32-bit unsigned value; a control flag to indicate whether listen * results need to be flushed to wpa_supplicant. */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG, /* A 8-bit unsigned value; reason code for P2P listen offload stop * event. */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON, /* keep last */ QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX = QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_acs_offload - Defines attributes to be used with * vendor command/event QCA_NL80211_VENDOR_SUBCMD_DO_ACS. * * @QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL: Required (u8). * Used with event to notify the primary channel number selected in ACS * operation. * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL is deprecated; use * QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY instead. * To maintain backward compatibility, QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL * is still used if either of the driver or user space application doesn't * support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL: Required (u8). * Used with event to notify the secondary channel number selected in ACS * operation. * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL is deprecated; use * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY instead. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL is still used if either of * the driver or user space application doesn't support 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE: Required (u8). * (a) Used with command to configure hw_mode from * enum qca_wlan_vendor_acs_hw_mode for ACS operation. * (b) Also used with event to notify the hw_mode of selected primary channel * in ACS operation. * * @QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED: Flag attribute. * Used with command to configure ACS operation for HT mode. * Disable (flag attribute not present) - HT disabled and * Enable (flag attribute present) - HT enabled. * * @QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED: Flag attribute. * Used with command to configure ACS operation for HT40 mode. * Disable (flag attribute not present) - HT40 disabled and * Enable (flag attribute present) - HT40 enabled. * * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED: Flag attribute. * Used with command to configure ACS operation for VHT mode. * Disable (flag attribute not present) - VHT disabled and * Enable (flag attribute present) - VHT enabled. * * @QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH: Optional (u16) with command and * mandatory with event. * If specified in command path, ACS operation is configured with the given * channel width (in MHz). * In event path, specifies the channel width of the primary channel selected. * * @QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST: Required and type is NLA_UNSPEC. * Used with command to configure channel list using an array of * channel numbers (u8). * Note: If both the driver and user-space application supports the 6 GHz band, * the driver mandates use of QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST whereas * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST is optional. * * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL: Required (u8). * Used with event to notify the VHT segment 0 center channel number selected in * ACS operation. The value is the index of the channel center frequency for * 20 MHz, 40 MHz, and 80 MHz channels. The value is the center frequency index * of the primary 80 MHz segment for 160 MHz and 80+80 MHz channels. * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL is deprecated; use * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY instead. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL is still used if either of * the driver or user space application doesn't support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL: Required (u8). * Used with event to notify the VHT segment 1 center channel number selected in * ACS operation. The value is zero for 20 MHz, 40 MHz, and 80 MHz channels. * The value is the index of the channel center frequency for 160 MHz channels * and the center frequency index of the secondary 80 MHz segment for 80+80 MHz * channels. * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL is deprecated; use * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY instead. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL is still used if either of * the driver or user space application doesn't support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST: Required and type is NLA_UNSPEC. * Used with command to configure the channel list using an array of channel * center frequencies in MHz (u32). * Note: If both the driver and user-space application supports the 6 GHz band, * the driver first parses the frequency list and if it fails to get a frequency * list, parses the channel list specified using * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST (considers only 2 GHz and 5 GHz channels in * QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST). * * @QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY: Required (u32). * Used with event to notify the primary channel center frequency (MHz) selected * in ACS operation. * Note: If the driver supports the 6 GHz band, the event sent from the driver * includes this attribute along with QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL. * * @QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY: Required (u32). * Used with event to notify the secondary channel center frequency (MHz) * selected in ACS operation. * Note: If the driver supports the 6 GHz band, the event sent from the driver * includes this attribute along with * QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL. * * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY: Required (u32). * Used with event to notify the VHT segment 0 center channel frequency (MHz) * selected in ACS operation. * Note: If the driver supports the 6 GHz band, the event sent from the driver * includes this attribute along with * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL. * * @QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY: Required (u32). * Used with event to notify the VHT segment 1 center channel frequency (MHz) * selected in ACS operation. * Note: If the driver supports the 6 GHz band, the event sent from the driver * includes this attribute along with * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL. * * @QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED: Flag attribute. * Used with command to notify the driver of EDMG request for ACS * operation. * * @QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL: Optional (u8). * Used with event to notify the EDMG channel number selected in ACS * operation. * EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL * * @QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP: Optional (u16). * Used with event to notify the puncture pattern selected in ACS operation. * Encoding for this attribute will follow the convention used in the Disabled * Subchannel Bitmap field of the EHT Operation IE. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED: Flag attribute. + * Used with command to configure ACS operation for EHT mode. + * Disable (flag attribute not present) - EHT disabled and + * Enable (flag attribute present) - EHT enabled. */ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL = 1, QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL = 2, QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE = 3, QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED = 4, QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED = 5, QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED = 6, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH = 7, QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST = 8, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL = 9, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL = 10, QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST = 11, QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY = 12, QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY = 13, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY = 14, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17, QCA_WLAN_VENDOR_ATTR_ACS_PUNCTURE_BITMAP = 18, + QCA_WLAN_VENDOR_ATTR_ACS_EHT_ENABLED = 19, /* keep last */ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ACS_MAX = QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_acs_hw_mode - Defines HW mode to be used with the * vendor command/event QCA_NL80211_VENDOR_SUBCMD_DO_ACS. * * @QCA_ACS_MODE_IEEE80211B: 802.11b mode * @QCA_ACS_MODE_IEEE80211G: 802.11g mode * @QCA_ACS_MODE_IEEE80211A: 802.11a mode * @QCA_ACS_MODE_IEEE80211AD: 802.11ad mode * @QCA_ACS_MODE_IEEE80211ANY: all modes * @QCA_ACS_MODE_IEEE80211AX: 802.11ax mode */ enum qca_wlan_vendor_acs_hw_mode { QCA_ACS_MODE_IEEE80211B, QCA_ACS_MODE_IEEE80211G, QCA_ACS_MODE_IEEE80211A, QCA_ACS_MODE_IEEE80211AD, QCA_ACS_MODE_IEEE80211ANY, QCA_ACS_MODE_IEEE80211AX, }; /** * enum qca_wlan_vendor_features - Vendor device/driver feature flags * * @QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD: Device supports key * management offload, a mechanism where the station's firmware * does the exchange with the AP to establish the temporal keys * after roaming, rather than having the user space wpa_supplicant do it. * @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic * band selection based on channel selection results. * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports * simultaneous off-channel operations. * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P * Listen offload; a mechanism where the station's firmware takes care of * responding to incoming Probe Request frames received from other P2P * Devices whilst in Listen state, rather than having the user space * wpa_supplicant do it. Information from received P2P requests are * forwarded from firmware to host whenever the host processor wakes up. * @QCA_WLAN_VENDOR_FEATURE_OCE_STA: Device supports all OCE non-AP STA * specific features. * @QCA_WLAN_VENDOR_FEATURE_OCE_AP: Device supports all OCE AP specific * features. * @QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON: Device supports OCE STA-CFON * specific features only. If a Device sets this bit but not the * %QCA_WLAN_VENDOR_FEATURE_OCE_AP, the userspace shall assume that * this Device may not support all OCE AP functionalities but can support * only OCE STA-CFON functionalities. * @QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY: Device supports self * managed regulatory. * @QCA_WLAN_VENDOR_FEATURE_TWT: Device supports TWT (Target Wake Time). * @QCA_WLAN_VENDOR_FEATURE_11AX: Device supports 802.11ax (HE) * @QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT: Device supports 6 GHz band operation * @QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG: Device is capable of receiving * and applying thermal configuration through * %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and * %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from * userspace. * @QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R: Device supports Adaptive 11r. * With Adaptive 11r feature, access points advertise the vendor * specific IEs and MDE but do not include FT AKM in the RSNE. * The Adaptive 11r supported stations are expected to identify * such vendor specific IEs and connect to the AP in FT mode though * the profile is configured in non-FT mode. * The driver-based SME cases also need to have this support for * Adaptive 11r to handle the connection and roaming scenarios. * This flag indicates the support for the same to the user space. * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports * concurrent network sessions on different Wi-Fi bands. This feature * capability is attributed to the hardware's capability to support * the same (e.g., DBS). * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT: Flag indicating whether the * responses for the respective TWT operations are asynchronous (separate * event message) from the driver. If not specified, the responses are * synchronous (in vendor command reply) to the request. Each TWT * operation is specifically mentioned (against its respective * documentation) to support either of these or both modes. * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits */ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0, QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1, QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2, QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD = 3, QCA_WLAN_VENDOR_FEATURE_OCE_STA = 4, QCA_WLAN_VENDOR_FEATURE_OCE_AP = 5, QCA_WLAN_VENDOR_FEATURE_OCE_STA_CFON = 6, QCA_WLAN_VENDOR_FEATURE_SELF_MANAGED_REGULATORY = 7, QCA_WLAN_VENDOR_FEATURE_TWT = 8, QCA_WLAN_VENDOR_FEATURE_11AX = 9, QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10, QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11, QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12, QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13, QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT = 14, NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; /** * enum qca_wlan_vendor_attr_data_offload_ind - Vendor Data Offload Indication * * @QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_SESSION: Session corresponding to * the offloaded data. * @QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_PROTOCOL: Protocol of the offloaded * data. * @QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_EVENT: Event type for the data offload * indication. */ enum qca_wlan_vendor_attr_data_offload_ind { QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_INVALID = 0, QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_SESSION, QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_PROTOCOL, QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_EVENT, /* keep last */ QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_MAX = QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_ocb_set_config - Vendor subcmd attributes to set * OCB config * * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT: Number of channels in the * configuration * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE: Size of the schedule * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY: Array of channels * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY: Array of channels to be * scheduled * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY: Array of NDL channel * information * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY: Array of NDL * active state configuration * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS: Configuration flags such as * OCB_CONFIG_FLAG_80211_FRAME_MODE * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM: Default TX parameters to * use in the case that a packet is sent without a TX control header * @QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_TA_MAX_DURATION: Max duration after the * last TA received that the local time set by TA is synchronous to other * communicating OCB STAs. */ enum qca_wlan_vendor_attr_ocb_set_config { QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_COUNT = 1, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_SIZE = 2, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_CHANNEL_ARRAY = 3, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_SCHEDULE_ARRAY = 4, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_CHANNEL_ARRAY = 5, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_NDL_ACTIVE_STATE_ARRAY = 6, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_FLAGS = 7, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_DEF_TX_PARAM = 8, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_TA_MAX_DURATION = 9, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_OCB_SET_CONFIG_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_ocb_set_utc_time - Vendor subcmd attributes to set * UTC time * * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE: The UTC time as an array of * 10 bytes * @QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR: The time error as an array of * 5 bytes */ enum qca_wlan_vendor_attr_ocb_set_utc_time { QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_VALUE = 1, QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_ERROR = 2, QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX = QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_ocb_start_timing_advert - Vendor subcmd attributes * to start sending timing advert frames * * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ: Cannel frequency * on which to send the frames * @QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE: Number of times * the frame is sent in 5 seconds */ enum qca_wlan_vendor_attr_ocb_start_timing_advert { QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_CHANNEL_FREQ = 1, QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_REPEAT_RATE = 2, QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX = QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_ocb_stop_timing_advert - Vendor subcmd attributes * to stop timing advert * * @QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ: The channel * frequency on which to stop the timing advert */ enum qca_wlan_vendor_attr_ocb_stop_timing_advert { QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ = 1, QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX = QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_ocb_get_tsf_response - Vendor subcmd attributes to * get TSF timer value * * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH: Higher 32 bits of the * timer * @QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW: Lower 32 bits of the timer */ enum qca_wlan_vendor_attr_ocb_get_tsf_resp { QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH = 1, QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW = 2, QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_MAX = QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_AFTER_LAST - 1 }; enum qca_vendor_attr_get_preferred_freq_list { QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID, /* A 32-unsigned value; the interface type/mode for which the preferred * frequency list is requested (see enum qca_iface_type for possible * values); used in GET_PREFERRED_FREQ_LIST command from user-space to * kernel and in the kernel response back to user-space. */ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE, /* An array of 32-unsigned values; values are frequency (MHz); sent * from kernel space to user space. */ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST, /* An array of nested values as per enum qca_wlan_vendor_attr_pcl * attribute. Each element contains frequency (MHz), weight, and flag * bit mask indicating how the frequency should be used in P2P * negotiation; sent from kernel space to user space. */ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_WEIGHED_PCL, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX = QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST - 1 }; enum qca_vendor_attr_probable_oper_channel { QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_INVALID, /* 32-bit unsigned value; indicates the connection/iface type likely to * come on this channel (see enum qca_iface_type). */ QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE, /* 32-bit unsigned value; the frequency (MHz) of the probable channel */ QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ, /* keep last */ QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX = QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST - 1 }; enum qca_iface_type { QCA_IFACE_TYPE_STA, QCA_IFACE_TYPE_AP, QCA_IFACE_TYPE_P2P_CLIENT, QCA_IFACE_TYPE_P2P_GO, QCA_IFACE_TYPE_IBSS, QCA_IFACE_TYPE_TDLS, }; enum qca_set_band { QCA_SETBAND_AUTO = 0, QCA_SETBAND_5G = BIT(0), QCA_SETBAND_2G = BIT(1), QCA_SETBAND_6G = BIT(2), }; /** * enum qca_access_policy - Access control policy * * Access control policy is applied on the configured IE * (QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE). * To be set with QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY. * * @QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED: Deny Wi-Fi connections which match * the specific configuration (IE) set, i.e., allow all the * connections which do not match the configuration. * @QCA_ACCESS_POLICY_DENY_UNLESS_LISTED: Accept Wi-Fi connections which match * the specific configuration (IE) set, i.e., deny all the * connections which do not match the configuration. */ enum qca_access_policy { QCA_ACCESS_POLICY_ACCEPT_UNLESS_LISTED, QCA_ACCESS_POLICY_DENY_UNLESS_LISTED, }; /** - * enum qca_vendor_attr_get_tsf: Vendor attributes for TSF capture - * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: enum qca_tsf_operation (u32) - * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Unsigned 64 bit TSF timer value - * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Unsigned 64 bit Synchronized - * SOC timer value at TSF capture + * enum qca_vendor_attr_tsf_cmd: Vendor attributes for TSF capture + * @QCA_WLAN_VENDOR_ATTR_TSF_CMD: Required (u32) + * Specify the TSF command. Possible values are defined in + * &enum qca_tsf_cmd. + * @QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE: Optional (u64) + * This attribute contains TSF timer value. This attribute is only available + * in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response. + * @QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE: Optional (u64) + * This attribute contains SOC timer value at TSF capture. This attribute is + * only available in %QCA_TSF_GET or %QCA_TSF_SYNC_GET response. + * @QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL: Optional (u32) + * This attribute is used to provide TSF sync interval and only applicable when + * TSF command is %QCA_TSF_SYNC_START. If this attribute is not provided, the + * driver will use the default value. Time unit is in milliseconds. */ enum qca_vendor_attr_tsf_cmd { QCA_WLAN_VENDOR_ATTR_TSF_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TSF_CMD, QCA_WLAN_VENDOR_ATTR_TSF_TIMER_VALUE, QCA_WLAN_VENDOR_ATTR_TSF_SOC_TIMER_VALUE, + QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL, QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TSF_MAX = QCA_WLAN_VENDOR_ATTR_TSF_AFTER_LAST - 1 }; /** - * enum qca_tsf_operation: TSF driver commands + * enum qca_tsf_cmd: TSF driver commands * @QCA_TSF_CAPTURE: Initiate TSF Capture * @QCA_TSF_GET: Get TSF capture value * @QCA_TSF_SYNC_GET: Initiate TSF capture and return with captured value * @QCA_TSF_AUTO_REPORT_ENABLE: Used in STA mode only. Once set, the target * will automatically send TSF report to the host. To query - * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be + * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY, this operation needs to be * initiated first. * @QCA_TSF_AUTO_REPORT_DISABLE: Used in STA mode only. Once set, the target * will not automatically send TSF report to the host. If - * QCA_TSF_AUTO_REPORT_ENABLE is initiated and - * QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this + * %QCA_TSF_AUTO_REPORT_ENABLE is initiated and + * %QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY is not queried anymore, this * operation needs to be initiated. + * @QCA_TSF_SYNC_START: Start periodic TSF sync feature. The driver periodically + * fetches TSF and host time mapping from the firmware with interval configured + * through the %QCA_WLAN_VENDOR_ATTR_TSF_SYNC_INTERVAL attribute. If the + * interval value is not provided the driver will use the default value. The + * userspace can query the TSF and host time mapping via the %QCA_TSF_GET + * command. + * @QCA_TSF_SYNC_STOP: Stop periodic TSF sync feature. */ enum qca_tsf_cmd { QCA_TSF_CAPTURE, QCA_TSF_GET, QCA_TSF_SYNC_GET, QCA_TSF_AUTO_REPORT_ENABLE, QCA_TSF_AUTO_REPORT_DISABLE, + QCA_TSF_SYNC_START, + QCA_TSF_SYNC_STOP, }; /** * enum qca_vendor_attr_wisa_cmd * @QCA_WLAN_VENDOR_ATTR_WISA_MODE: WISA mode value (u32) * WISA setup vendor commands */ enum qca_vendor_attr_wisa_cmd { QCA_WLAN_VENDOR_ATTR_WISA_INVALID = 0, QCA_WLAN_VENDOR_ATTR_WISA_MODE, QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WISA_MAX = QCA_WLAN_VENDOR_ATTR_WISA_AFTER_LAST - 1 }; /* IEEE 802.11 Vendor Specific elements */ /** * enum qca_vendor_element_id - QCA Vendor Specific element types * * These values are used to identify QCA Vendor Specific elements. The * payload of the element starts with the three octet OUI (OUI_QCA) and * is followed by a single octet type which is defined by this enum. * * @QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST: P2P preferred channel list. * This element can be used to specify preference order for supported * channels. The channels in this list are in preference order (the first * one has the highest preference) and are described as a pair of * (global) Operating Class and Channel Number (each one octet) fields. * * This extends the standard P2P functionality by providing option to have * more than one preferred operating channel. When this element is present, * it replaces the preference indicated in the Operating Channel attribute. * For supporting other implementations, the Operating Channel attribute is * expected to be used with the highest preference channel. Similarly, all * the channels included in this Preferred channel list element are * expected to be included in the Channel List attribute. * * This vendor element may be included in GO Negotiation Request, P2P * Invitation Request, and Provision Discovery Request frames. * * @QCA_VENDOR_ELEM_HE_CAPAB: HE Capabilities element. * This element can be used for pre-standard publication testing of HE * before P802.11ax draft assigns the element ID. The payload of this * vendor specific element is defined by the latest P802.11ax draft. * Please note that the draft is still work in progress and this element * payload is subject to change. * * @QCA_VENDOR_ELEM_HE_OPER: HE Operation element. * This element can be used for pre-standard publication testing of HE * before P802.11ax draft assigns the element ID. The payload of this * vendor specific element is defined by the latest P802.11ax draft. * Please note that the draft is still work in progress and this element * payload is subject to change. * * @QCA_VENDOR_ELEM_RAPS: RAPS element (OFDMA-based Random Access Parameter Set * element). * This element can be used for pre-standard publication testing of HE * before P802.11ax draft assigns the element ID extension. The payload of * this vendor specific element is defined by the latest P802.11ax draft * (not including the Element ID Extension field). Please note that the * draft is still work in progress and this element payload is subject to * change. * * @QCA_VENDOR_ELEM_MU_EDCA_PARAMS: MU EDCA Parameter Set element. * This element can be used for pre-standard publication testing of HE * before P802.11ax draft assigns the element ID extension. The payload of * this vendor specific element is defined by the latest P802.11ax draft * (not including the Element ID Extension field). Please note that the * draft is still work in progress and this element payload is subject to * change. * * @QCA_VENDOR_ELEM_BSS_COLOR_CHANGE: BSS Color Change Announcement element. * This element can be used for pre-standard publication testing of HE * before P802.11ax draft assigns the element ID extension. The payload of * this vendor specific element is defined by the latest P802.11ax draft * (not including the Element ID Extension field). Please note that the * draft is still work in progress and this element payload is subject to * change. * * @QCA_VENDOR_ELEM_ALLPLAY: Allplay element */ enum qca_vendor_element_id { QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0, QCA_VENDOR_ELEM_HE_CAPAB = 1, QCA_VENDOR_ELEM_HE_OPER = 2, QCA_VENDOR_ELEM_RAPS = 3, QCA_VENDOR_ELEM_MU_EDCA_PARAMS = 4, QCA_VENDOR_ELEM_BSS_COLOR_CHANGE = 5, QCA_VENDOR_ELEM_ALLPLAY = 6, }; /** * enum qca_wlan_vendor_scan_priority - Specifies the valid values that the * vendor scan attribute QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY can take. * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW: Very low priority * @QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW: Low priority * @QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM: Medium priority * @QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH: High priority * @QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH: Very high priority */ enum qca_wlan_vendor_scan_priority { QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_LOW = 0, QCA_WLAN_VENDOR_SCAN_PRIORITY_LOW = 1, QCA_WLAN_VENDOR_SCAN_PRIORITY_MEDIUM = 2, QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH = 3, QCA_WLAN_VENDOR_SCAN_PRIORITY_VERY_HIGH = 4, }; /** * enum qca_wlan_vendor_attr_scan - Specifies vendor scan attributes * * @QCA_WLAN_VENDOR_ATTR_SCAN_IE: IEs that should be included as part of scan * @QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES: Nested unsigned 32-bit attributes * with frequencies to be scanned (in MHz) * @QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS: Nested attribute with SSIDs to be scanned * @QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES: Nested array attribute of supported * rates to be included * @QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE: flag used to send probe requests * at non CCK rate in 2GHz band * @QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS: Unsigned 32-bit scan flags * @QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE: Unsigned 64-bit cookie provided by the * driver for the specific scan request * @QCA_WLAN_VENDOR_ATTR_SCAN_STATUS: Unsigned 8-bit status of the scan * request decoded as in enum scan_status * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC: 6-byte MAC address to use when randomisation * scan flag is set * @QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK: 6-byte MAC address mask to be used with * randomisation * @QCA_WLAN_VENDOR_ATTR_SCAN_BSSID: 6-byte MAC address representing the * specific BSSID to scan for. * @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in * microseconds. This is a common value which applies across all * frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES. * @QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY: Priority of vendor scan relative to * other scan requests. It is a u32 attribute and takes values from enum * qca_wlan_vendor_scan_priority. This is an optional attribute. * If this attribute is not configured, the driver shall use * QCA_WLAN_VENDOR_SCAN_PRIORITY_HIGH as the priority of vendor scan. */ enum qca_wlan_vendor_attr_scan { QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0, QCA_WLAN_VENDOR_ATTR_SCAN_IE = 1, QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES = 2, QCA_WLAN_VENDOR_ATTR_SCAN_SSIDS = 3, QCA_WLAN_VENDOR_ATTR_SCAN_SUPP_RATES = 4, QCA_WLAN_VENDOR_ATTR_SCAN_TX_NO_CCK_RATE = 5, QCA_WLAN_VENDOR_ATTR_SCAN_FLAGS = 6, QCA_WLAN_VENDOR_ATTR_SCAN_COOKIE = 7, QCA_WLAN_VENDOR_ATTR_SCAN_STATUS = 8, QCA_WLAN_VENDOR_ATTR_SCAN_MAC = 9, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10, QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11, QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12, QCA_WLAN_VENDOR_ATTR_SCAN_PRIORITY = 13, QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SCAN_MAX = QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1 }; /** * enum scan_status - Specifies the valid values the vendor scan attribute * QCA_WLAN_VENDOR_ATTR_SCAN_STATUS can take * * @VENDOR_SCAN_STATUS_NEW_RESULTS: implies the vendor scan is successful with * new scan results * @VENDOR_SCAN_STATUS_ABORTED: implies the vendor scan was aborted in-between */ enum scan_status { VENDOR_SCAN_STATUS_NEW_RESULTS, VENDOR_SCAN_STATUS_ABORTED, VENDOR_SCAN_STATUS_MAX, }; /** * enum qca_vendor_attr_ota_test - Specifies the values for vendor * command QCA_NL80211_VENDOR_SUBCMD_OTA_TEST * @QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE: enable ota test */ enum qca_vendor_attr_ota_test { QCA_WLAN_VENDOR_ATTR_OTA_TEST_INVALID, /* 8-bit unsigned value to indicate if OTA test is enabled */ QCA_WLAN_VENDOR_ATTR_OTA_TEST_ENABLE, /* keep last */ QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OTA_TEST_MAX = QCA_WLAN_VENDOR_ATTR_OTA_TEST_AFTER_LAST - 1 }; /** * enum qca_vendor_attr_txpower_scale - vendor sub commands index * * @QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE: scaling value */ enum qca_vendor_attr_txpower_scale { QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_INVALID, /* 8-bit unsigned value to indicate the scaling of tx power */ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE, /* keep last */ QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_MAX = QCA_WLAN_VENDOR_ATTR_TXPOWER_SCALE_AFTER_LAST - 1 }; /** * enum qca_vendor_attr_txpower_decr_db - Attributes for TX power decrease * * These attributes are used with QCA_NL80211_VENDOR_SUBCMD_SET_TXPOWER_DECR_DB. */ enum qca_vendor_attr_txpower_decr_db { QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_INVALID, /* 8-bit unsigned value to indicate the reduction of TX power in dB for * a virtual interface. */ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB, /* keep last */ QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_MAX = QCA_WLAN_VENDOR_ATTR_TXPOWER_DECR_DB_AFTER_LAST - 1 }; /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_SET_WIFI_CONFIGURATION and * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION subcommands. */ enum qca_wlan_vendor_attr_config { QCA_WLAN_VENDOR_ATTR_CONFIG_INVALID = 0, /* Unsigned 32-bit value to set the DTIM period. * Whether the wifi chipset wakes at every dtim beacon or a multiple of * the DTIM period. If DTIM is set to 3, the STA shall wake up every 3 * DTIM beacons. */ QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_DTIM = 1, /* Unsigned 32-bit value to set the wifi_iface stats averaging factor * used to calculate statistics like average the TSF offset or average * number of frame leaked. * For instance, upon Beacon frame reception: * current_avg = ((beacon_TSF - TBTT) * factor + previous_avg * (0x10000 - factor) ) / 0x10000 * For instance, when evaluating leaky APs: * current_avg = ((num frame received within guard time) * factor + previous_avg * (0x10000 - factor)) / 0x10000 */ QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR = 2, /* Unsigned 32-bit value to configure guard time, i.e., when * implementing IEEE power management based on frame control PM bit, how * long the driver waits before shutting down the radio and after * receiving an ACK frame for a Data frame with PM bit set. */ QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME = 3, /* Unsigned 32-bit value to change the FTM capability dynamically */ QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT = 4, /* Unsigned 16-bit value to configure maximum TX rate dynamically */ QCA_WLAN_VENDOR_ATTR_CONF_TX_RATE = 5, /* Unsigned 32-bit value to configure the number of continuous * Beacon Miss which shall be used by the firmware to penalize * the RSSI. */ QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS = 6, /* Unsigned 8-bit value to configure the channel avoidance indication * behavior. Firmware to send only one indication and ignore duplicate * indications when set to avoid multiple Apps wakeups. */ QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND = 7, /* 8-bit unsigned value to configure the maximum TX MPDU for * aggregation. */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MPDU_AGGREGATION = 8, /* 8-bit unsigned value to configure the maximum RX MPDU for * aggregation. */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION = 9, /* 8-bit unsigned value to configure the Non aggregrate/11g sw * retry threshold (0 disable, 31 max). */ QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY = 10, /* 8-bit unsigned value to configure the aggregrate sw * retry threshold (0 disable, 31 max). */ QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY = 11, /* 8-bit unsigned value to configure the MGMT frame * retry threshold (0 disable, 31 max). */ QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY = 12, /* 8-bit unsigned value to configure the CTRL frame * retry threshold (0 disable, 31 max). */ QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY = 13, /* 8-bit unsigned value to configure the propagation delay for * 2G/5G band (0~63, units in us) */ QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY = 14, /* Unsigned 32-bit value to configure the number of unicast TX fail * packet count. The peer is disconnected once this threshold is * reached. */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT = 15, /* Attribute used to set scan default IEs to the driver. * * These IEs can be used by scan operations that will be initiated by * the driver/firmware. * * For further scan requests coming to the driver, these IEs should be * merged with the IEs received along with scan request coming to the * driver. If a particular IE is present in the scan default IEs but not * present in the scan request, then that IE should be added to the IEs * sent in the Probe Request frames for that scan request. */ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_DEFAULT_IES = 16, /* Unsigned 32-bit attribute for generic commands */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_COMMAND = 17, /* Unsigned 32-bit value attribute for generic commands */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_VALUE = 18, /* Unsigned 32-bit data attribute for generic command response */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA = 19, /* Unsigned 32-bit length attribute for * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_LENGTH = 20, /* Unsigned 32-bit flags attribute for * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA */ QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_FLAGS = 21, /* Unsigned 32-bit, defining the access policy. * See enum qca_access_policy. Used with * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST. */ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY = 22, /* Sets the list of full set of IEs for which a specific access policy * has to be applied. Used along with * QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY to control the access. * Zero length payload can be used to clear this access constraint. */ QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST = 23, /* Unsigned 32-bit, specifies the interface index (netdev) for which the * corresponding configurations are applied. If the interface index is * not specified, the configurations are attributed to the respective * wiphy. */ QCA_WLAN_VENDOR_ATTR_CONFIG_IFINDEX = 24, /* 8-bit unsigned value to trigger QPower: 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER = 25, /* 8-bit unsigned value to configure the driver and below layers to * ignore the assoc disallowed set by APs while connecting * 1-Ignore, 0-Don't ignore */ QCA_WLAN_VENDOR_ATTR_CONFIG_IGNORE_ASSOC_DISALLOWED = 26, /* 32-bit unsigned value to trigger antenna diversity features: * 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA = 27, /* 32-bit unsigned value to configure specific chain antenna */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN = 28, /* 32-bit unsigned value to trigger cycle selftest * 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST = 29, /* 32-bit unsigned to configure the cycle time of selftest * the unit is micro-second */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST_INTVL = 30, /* 32-bit unsigned value to set reorder timeout for AC_VO */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VOICE = 31, /* 32-bit unsigned value to set reorder timeout for AC_VI */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_VIDEO = 32, /* 32-bit unsigned value to set reorder timeout for AC_BE */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BESTEFFORT = 33, /* 32-bit unsigned value to set reorder timeout for AC_BK */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_REORDER_TIMEOUT_BACKGROUND = 34, /* 6-byte MAC address to point out the specific peer */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_PEER_MAC = 35, /* 32-bit unsigned value to set window size for specific peer */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_BLOCKSIZE_WINLIMIT = 36, /* 8-bit unsigned value to set the beacon miss threshold in 2.4 GHz */ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_24 = 37, /* 8-bit unsigned value to set the beacon miss threshold in 5 GHz */ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_MISS_THRESHOLD_5 = 38, /* 32-bit unsigned value to configure 5 or 10 MHz channel width for * station device while in disconnect state. The attribute use the * value of enum nl80211_chan_width: NL80211_CHAN_WIDTH_5 means 5 MHz, * NL80211_CHAN_WIDTH_10 means 10 MHz. If set, the device work in 5 or * 10 MHz channel width, the station will not connect to a BSS using 20 * MHz or higher bandwidth. Set to NL80211_CHAN_WIDTH_20_NOHT to * clear this constraint. */ QCA_WLAN_VENDOR_ATTR_CONFIG_SUB20_CHAN_WIDTH = 39, /* 32-bit unsigned value to configure the propagation absolute delay * for 2G/5G band (units in us) */ QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_ABS_DELAY = 40, /* 32-bit unsigned value to set probe period */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_PERIOD = 41, /* 32-bit unsigned value to set stay period */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_STAY_PERIOD = 42, /* 32-bit unsigned value to set snr diff */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SNR_DIFF = 43, /* 32-bit unsigned value to set probe dwell time */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_PROBE_DWELL_TIME = 44, /* 32-bit unsigned value to set mgmt snr weight */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_MGMT_SNR_WEIGHT = 45, /* 32-bit unsigned value to set data snr weight */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_DATA_SNR_WEIGHT = 46, /* 32-bit unsigned value to set ack snr weight */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ACK_SNR_WEIGHT = 47, /* 32-bit unsigned value to configure the listen interval. * This is in units of beacon intervals. This configuration alters * the negotiated listen interval with the AP during the connection. * It is highly recommended to configure a value less than or equal to * the one negotiated during the association. Configuring any greater * value can have adverse effects (frame loss, AP disassociating STA, * etc.). */ QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL = 48, /* * 8 bit unsigned value that is set on an AP/GO virtual interface to * disable operations that would cause the AP/GO to leave its operating * channel. * * This will restrict the scans to the AP/GO operating channel and the * channels of the other band, if DBS is supported.A STA/CLI interface * brought up after this setting is enabled, will be restricted to * connecting to devices only on the AP/GO interface's operating channel * or on the other band in DBS case. P2P supported channel list is * modified, to only include AP interface's operating-channel and the * channels of the other band if DBS is supported. * * These restrictions are only applicable as long as the AP/GO interface * is alive. If the AP/GO interface is brought down then this * setting/restriction is forgotten. * * If this variable is set on an AP/GO interface while a multi-channel * concurrent session is active, it has no effect on the operation of * the current interfaces, other than restricting the scan to the AP/GO * operating channel and the other band channels if DBS is supported. * However, if the STA is brought down and restarted then the new STA * connection will either be formed on the AP/GO channel or on the * other band in a DBS case. This is because of the scan being * restricted on these channels as mentioned above. * * 1-Restrict / 0-Don't restrict offchannel operations. */ QCA_WLAN_VENDOR_ATTR_CONFIG_RESTRICT_OFFCHANNEL = 49, /* * 8 bit unsigned value to enable/disable LRO (Large Receive Offload) * on an interface. * 1 - Enable, 0 - Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_LRO = 50, /* * 8 bit unsigned value to globally enable/disable scan * 1 - Enable, 0 - Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE = 51, /* 8-bit unsigned value to set the total beacon miss count * This parameter will set the total beacon miss count. */ QCA_WLAN_VENDOR_ATTR_CONFIG_TOTAL_BEACON_MISS_COUNT = 52, /* Unsigned 32-bit value to configure the number of continuous * Beacon Miss which shall be used by the firmware to penalize * the RSSI for BTC. */ QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS_BTC = 53, /* 8-bit unsigned value to configure the driver and below layers to * enable/disable all FILS features. * 0-enable, 1-disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_DISABLE_FILS = 54, /* 16-bit unsigned value to configure the level of WLAN latency * module. See enum qca_wlan_vendor_attr_config_latency_level. */ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL = 55, /* 8-bit unsigned value indicating the driver to use the RSNE as-is from * the connect interface. Exclusively used for the scenarios where the * device is used as a test bed device with special functionality and * not recommended for production. This helps driver to not validate the * RSNE passed from user space and thus allow arbitrary IE data to be * used for testing purposes. * 1-enable, 0-disable. * Applications set/reset this configuration. If not reset, this * parameter remains in use until the driver is unloaded. */ QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE = 56, /* 8-bit unsigned value to trigger green Tx power saving. * 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_GTX = 57, /* Attribute to configure disconnect IEs to the driver. * This carries an array of unsigned 8-bit characters. * * If this is configured, driver shall fill the IEs in disassoc/deauth * frame. * These IEs are expected to be considered only for the next * immediate disconnection (disassoc/deauth frame) originated by * the DUT, irrespective of the entity (user space/driver/firmware) * triggering the disconnection. * The host drivers are not expected to use the IEs set through * this interface for further disconnections after the first immediate * disconnection initiated post the configuration. * If the IEs are also updated through cfg80211 interface (after the * enhancement to cfg80211_disconnect), host driver is expected to * take the union of IEs from both of these interfaces and send in * further disassoc/deauth frames. */ QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES = 58, /* 8-bit unsigned value for ELNA bypass. * 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS = 59, /* 8-bit unsigned value. This attribute enables/disables the host driver * to send the Beacon Report Response with failure reason for the * scenarios where STA cannot honor the Beacon Report Request from AP. * 1-Enable, 0-Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL = 60, /* 8-bit unsigned value. This attribute enables/disables the host driver * to send roam reason information in the Reassociation Request frame to * the target AP when roaming within the same ESS. * 1-Enable, 0-Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON = 61, /* 32-bit unsigned value to configure different PHY modes to the * driver/firmware. The possible values are defined in * enum qca_wlan_vendor_phy_mode. The configuration will be reset to * default value, i.e., QCA_WLAN_VENDOR_PHY_MODE_AUTO upon restarting * the driver. */ QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE = 62, /* 8-bit unsigned value to configure the maximum supported channel width * for STA mode. If this value is configured when STA is in connected * state, it should not exceed the negotiated channel width. If it is * configured when STA is in disconnected state, the configured value * will take effect for the next immediate connection. * Possible values are: * NL80211_CHAN_WIDTH_20 * NL80211_CHAN_WIDTH_40 * NL80211_CHAN_WIDTH_80 * NL80211_CHAN_WIDTH_80P80 * NL80211_CHAN_WIDTH_160 */ QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH = 63, /* 8-bit unsigned value to enable/disable dynamic bandwidth adjustment. * This attribute is only applicable for STA mode. When dynamic * bandwidth adjustment is disabled, STA will use static channel width * the value of which is negotiated during connection. * 1-enable (default), 0-disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW = 64, /* 8-bit unsigned value to configure the maximum number of subframes of * TX MSDU for aggregation. Possible values are 0-31. When set to 0, * it is decided by the hardware. */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION = 65, /* 8-bit unsigned value to configure the maximum number of subframes of * RX MSDU for aggregation. Possible values are 0-31. When set to 0, * it is decided by the hardware. */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION = 66, /* 8-bit unsigned value. This attribute is used to dynamically * enable/disable the LDPC capability of the device. When configured in * the disconnected state, the updated configuration will be considered * for the immediately following connection attempt. If this * configuration is modified while the device is in the connected state, * the LDPC TX will be updated with this configuration immediately, * while the LDPC RX configuration update will take place starting from * the subsequent association attempt. * 1-Enable, 0-Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC = 67, /* 8-bit unsigned value. This attribute is used to dynamically * enable/disable the TX STBC capability of the device. When configured * in the disconnected state, the updated configuration will be * considered for the immediately following connection attempt. If the * connection is formed with TX STBC enabled and if this configuration * is disabled during that association, the TX will be impacted * immediately. Further connection attempts will disable TX STBC. * However, enabling the TX STBC for a connected session with disabled * capability is not allowed and will fail. * 1-Enable, 0-Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC = 68, /* 8-bit unsigned value. This attribute is used to dynamically * enable/disable the RX STBC capability of the device. When configured * in the disconnected state, the updated configuration will be * considered for the immediately following connection attempt. If the * configuration is modified in the connected state, there will be no * impact for the current association, but further connection attempts * will use the updated configuration. * 1-Enable, 0-Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC = 69, /* 8-bit unsigned value. This attribute is used to dynamically configure * the number of spatial streams. When configured in the disconnected * state, the updated configuration will be considered for the * immediately following connection attempt. If the NSS is updated after * the connection, the updated NSS value is notified to the peer using * the Operating Mode Notification/Spatial Multiplexing Power Save * frame. The updated NSS value after the connection shall not be * greater than the one negotiated during the connection. Any such * higher value configuration shall be returned with a failure. * Only symmetric NSS configuration (such as 2X2 or 1X1) can be done * using this attribute. QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS and * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attributes shall be used to * configure the asymmetric NSS configuration (such as 1X2). */ QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70, /* 8-bit unsigned value to trigger Optimized Power Management: * 1-Enable, 0-Disable */ QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT = 71, /* 8-bit unsigned value. This attribute takes the QoS/access category * value represented by the enum qca_wlan_ac_type and expects the driver * to upgrade the UDP frames to this access category. The value of * QCA_WLAN_AC_ALL is invalid for this attribute. This will override the * DSCP value configured in the frame with the intention to only upgrade * the access category. That said, it is not intended to downgrade the * access category for the frames. * Set the value to QCA_WLAN_AC_BK if the QoS upgrade needs to be * disabled, as BK is of the lowest priority and an upgrade to it does * not result in any changes for the frames. */ QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72, /* 8-bit unsigned value. This attribute is used to dynamically configure * the number of chains to be used for transmitting data. This * configuration is allowed only when in connected state and will be * effective until disconnected. The driver rejects this configuration * if the number of spatial streams being used in the current connection * cannot be supported by this configuration. */ QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS = 73, /* 8-bit unsigned value. This attribute is used to dynamically configure * the number of chains to be used for receiving data. This * configuration is allowed only when in connected state and will be * effective until disconnected. The driver rejects this configuration * if the number of spatial streams being used in the current connection * cannot be supported by this configuration. */ QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS = 74, /* 8-bit unsigned value to configure ANI setting type. * See &enum qca_wlan_ani_setting for possible values. */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING = 75, /* 32-bit signed value to configure ANI level. This is used when * ANI settings type is &QCA_WLAN_ANI_SETTING_FIXED. * The set and get of ANI level with &QCA_WLAN_ANI_SETTING_AUTO * is invalid, the driver will return a failure. */ QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76, /* 8-bit unsigned value. This attribute is used to dynamically configure * the number of spatial streams used for transmitting the data. When * configured in the disconnected state, the configured value will * be considered for the following connection attempt. * If the NSS is updated after the connection, the updated NSS value * is notified to the peer using the Operating Mode Notification/Spatial * Multiplexing Power Save frame. * The TX NSS value configured after the connection shall not be greater * than the value negotiated during the connection. Any such higher * value configuration shall be treated as invalid configuration by * the driver. This attribute shall be configured along with * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric * configuration (such as 2X2 or 1X1) or the asymmetric * configuration (such as 1X2). * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS. */ QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77, /* 8-bit unsigned value. This attribute is used to dynamically configure * the number of spatial streams used for receiving the data. When * configured in the disconnected state, the configured value will * be considered for the following connection attempt. * If the NSS is updated after the connection, the updated NSS value * is notified to the peer using the Operating Mode Notification/Spatial * Multiplexing Power Save frame. * The RX NSS value configured after the connection shall not be greater * than the value negotiated during the connection. Any such higher * value configuration shall be treated as invalid configuration by * the driver. This attribute shall be configured along with * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric * configuration (such as 2X2 or 1X1) or the asymmetric * configuration (such as 1X2). * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS. */ QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78, /* * 8-bit unsigned value. This attribute, when set, indicates whether the * specified interface is the primary STA interface when there are more * than one STA interfaces concurrently active. * * This configuration helps the firmware/hardware to support certain * features (e.g., roaming) on this primary interface, if the same * cannot be supported on the concurrent STA interfaces simultaneously. * * This configuration is only applicable for a single STA interface on * a device and gives the priority for it only over other concurrent STA * interfaces. * * If the device is a multi wiphy/soc, this configuration applies to a * single STA interface across the wiphys. * * 1-Enable (is the primary STA), 0-Disable (is not the primary STA) */ QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY = 79, /* * 8-bit unsigned value. This attribute can be used to configure the * driver to enable/disable FT-over-DS feature. Possible values for * this attribute are 1-Enable and 0-Disable. */ QCA_WLAN_VENDOR_ATTR_CONFIG_FT_OVER_DS = 80, /* * 8-bit unsigned value. This attribute can be used to configure the * firmware to enable/disable ARP/NS offload feature. Possible values * for this attribute are 0-Disable and 1-Enable. * * This attribute is only applicable for STA/P2P-Client interface, * and is optional, default behavior is ARP/NS offload enabled. * * This attribute can be set in disconnected and connected state, and * will restore to the default behavior if the interface is closed. */ QCA_WLAN_VENDOR_ATTR_CONFIG_ARP_NS_OFFLOAD = 81, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1, }; /* Compatibility defines for previously used incorrect enum * qca_wlan_vendor_attr_config names. These values should not be used in any * new implementation. */ #define QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES \ QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES #define QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL \ QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL /** * enum qca_wlan_ani_setting - ANI setting type * @QCA_WLAN_ANI_SETTING_AUTO: Automatically determine ANI level * @QCA_WLAN_ANI_SETTING_FIXED: Fix ANI level to the dBm parameter */ enum qca_wlan_ani_setting { QCA_WLAN_ANI_SETTING_AUTO = 0, QCA_WLAN_ANI_SETTING_FIXED = 1, }; /** * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration * * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL: Optional (u8) * Channel number on which Access Point should restart. * Note: If both the driver and user space application supports the 6 GHz band, * this attribute is deprecated and QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY * should be used. * To maintain backward compatibility, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL * is still used if either of the driver or user space application doesn't * support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY: Optional (u32) * Channel center frequency (MHz) on which the access point should restart. */ enum qca_wlan_vendor_attr_sap_config { QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_INVALID = 0, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_CHANNEL = 1, /* List of frequencies on which AP is expected to operate. * This is irrespective of ACS configuration. This list is a priority * based one and is looked for before the AP is created to ensure the * best concurrency sessions (avoid MCC and use DBS/SCC) co-exist in * the system. */ QCA_WLAN_VENDOR_ATTR_SAP_MANDATORY_FREQUENCY_LIST = 2, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_FREQUENCY = 3, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_sap_conditional_chan_switch - Parameters for AP * conditional channel switch */ enum qca_wlan_vendor_attr_sap_conditional_chan_switch { QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0, /* Priority based frequency list (an array of u32 values in host byte * order) */ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1, /* Status of the conditional switch (u32). * 0: Success, Non-zero: Failure */ QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS = 2, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX = QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST - 1, }; /** * enum qca_wlan_gpio_attr - Parameters for GPIO configuration * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND: Required (u32) * value to specify the GPIO command. Please refer to enum qca_gpio_cmd_type * for the available values. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM: Required (u32) * value to specify the GPIO number. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG or %QCA_WLAN_VENDOR_GPIO_OUTPUT. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE: Required (u32) * value to specify the GPIO output level. Please refer to enum qca_gpio_value * for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_OUTPUT. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32) * value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type * for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG and * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG * attribute is present. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32) * value to specify the GPIO interrupt mode. Please refer to enum * qca_gpio_interrupt_mode for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG and * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG * attribute is present. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32) * value to specify the GPIO direction. Please refer to enum qca_gpio_direction * for the available values. * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG and * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG * attribute is present. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32) * Value to specify the mux config. Meaning of a given value is dependent * on the target chipset and GPIO pin. Must be of the range 0-15. * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0. * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32) * Value to specify the drive, refer to enum qca_gpio_drive. * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0). * * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag) * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all * other parameters for the given GPIO will be obtained from internal * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be * specified to indicate the GPIO pin being configured. */ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0, /* Unsigned 32-bit attribute for GPIO command */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND = 1, /* Unsigned 32-bit attribute for GPIO PIN number to configure */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM = 2, /* Unsigned 32-bit attribute for GPIO value to configure */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE = 3, /* Unsigned 32-bit attribute for GPIO pull type */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE = 4, /* Unsigned 32-bit attribute for GPIO interrupt mode */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5, /* Unsigned 32-bit attribute for GPIO direction to configure */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6, /* Unsigned 32-bit attribute for GPIO mux config */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7, /* Unsigned 32-bit attribute for GPIO drive */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8, /* Flag attribute for using internal GPIO configuration */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9, /* keep last */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST, QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MAX = QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1 }; /** * enum gpio_cmd_type - GPIO configuration command type * @QCA_WLAN_VENDOR_GPIO_CONFIG: Set GPIO configuration info * @QCA_WLAN_VENDOR_GPIO_OUTPUT: Set GPIO output level */ enum qca_gpio_cmd_type { QCA_WLAN_VENDOR_GPIO_CONFIG = 0, QCA_WLAN_VENDOR_GPIO_OUTPUT = 1, }; /** * enum qca_gpio_pull_type - GPIO pull type * @QCA_WLAN_GPIO_PULL_NONE: Set GPIO pull type to none * @QCA_WLAN_GPIO_PULL_UP: Set GPIO pull up * @QCA_WLAN_GPIO_PULL_DOWN: Set GPIO pull down */ enum qca_gpio_pull_type { QCA_WLAN_GPIO_PULL_NONE = 0, QCA_WLAN_GPIO_PULL_UP = 1, QCA_WLAN_GPIO_PULL_DOWN = 2, QCA_WLAN_GPIO_PULL_MAX, }; /** * enum qca_gpio_direction - GPIO direction * @QCA_WLAN_GPIO_INPUT: Set GPIO as input mode * @QCA_WLAN_GPIO_OUTPUT: Set GPIO as output mode * @QCA_WLAN_GPIO_VALUE_MAX: Invalid value */ enum qca_gpio_direction { QCA_WLAN_GPIO_INPUT = 0, QCA_WLAN_GPIO_OUTPUT = 1, QCA_WLAN_GPIO_DIR_MAX, }; /** * enum qca_gpio_value - GPIO Value * @QCA_WLAN_GPIO_LEVEL_LOW: set gpio output level to low * @QCA_WLAN_GPIO_LEVEL_HIGH: set gpio output level to high * @QCA_WLAN_GPIO_LEVEL_MAX: Invalid value */ enum qca_gpio_value { QCA_WLAN_GPIO_LEVEL_LOW = 0, QCA_WLAN_GPIO_LEVEL_HIGH = 1, QCA_WLAN_GPIO_LEVEL_MAX, }; /** * enum gpio_interrupt_mode - GPIO interrupt mode * @QCA_WLAN_GPIO_INTMODE_DISABLE: Disable interrupt trigger * @QCA_WLAN_GPIO_INTMODE_RISING_EDGE: Interrupt with GPIO rising edge trigger * @QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: Interrupt with GPIO falling edge trigger * @QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: Interrupt with GPIO both edge trigger * @QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: Interrupt with GPIO level low trigger * @QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: Interrupt with GPIO level high trigger * @QCA_WLAN_GPIO_INTMODE_MAX: Invalid value */ enum qca_gpio_interrupt_mode { QCA_WLAN_GPIO_INTMODE_DISABLE = 0, QCA_WLAN_GPIO_INTMODE_RISING_EDGE = 1, QCA_WLAN_GPIO_INTMODE_FALLING_EDGE = 2, QCA_WLAN_GPIO_INTMODE_BOTH_EDGE = 3, QCA_WLAN_GPIO_INTMODE_LEVEL_LOW = 4, QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH = 5, QCA_WLAN_GPIO_INTMODE_MAX, }; /** * enum qca_gpio_drive - GPIO drive * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA * @QCA_WLAN_GPIO_DRIVE_MAX: invalid GPIO drive */ enum qca_gpio_drive { QCA_WLAN_GPIO_DRIVE_2MA = 0, QCA_WLAN_GPIO_DRIVE_4MA = 1, QCA_WLAN_GPIO_DRIVE_6MA = 2, QCA_WLAN_GPIO_DRIVE_8MA = 3, QCA_WLAN_GPIO_DRIVE_10MA = 4, QCA_WLAN_GPIO_DRIVE_12MA = 5, QCA_WLAN_GPIO_DRIVE_14MA = 6, QCA_WLAN_GPIO_DRIVE_16MA = 7, QCA_WLAN_GPIO_DRIVE_MAX, }; /** * qca_wlan_set_qdepth_thresh_attr - Parameters for setting * MSDUQ depth threshold per peer per tid in the target * * Associated Vendor Command: * QCA_NL80211_VENDOR_SUBCMD_SET_QDEPTH_THRESH */ enum qca_wlan_set_qdepth_thresh_attr { QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_INVALID = 0, /* 6-byte MAC address */ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAC_ADDR, /* Unsigned 32-bit attribute for holding the TID */ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_TID, /* Unsigned 32-bit attribute for holding the update mask * bit 0 - Update high priority msdu qdepth threshold * bit 1 - Update low priority msdu qdepth threshold * bit 2 - Update UDP msdu qdepth threshold * bit 3 - Update Non UDP msdu qdepth threshold * rest of bits are reserved */ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_UPDATE_MASK, /* Unsigned 32-bit attribute for holding the threshold value */ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_VALUE, /* keep last */ QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST, QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_MAX = QCA_WLAN_VENDOR_ATTR_QDEPTH_THRESH_LAST - 1, }; /** * enum qca_acs_dfs_mode - Defines different types of DFS channel * configurations for ACS operation. * * @QCA_ACS_DFS_MODE_NONE: Refer to invalid DFS mode * @QCA_ACS_DFS_MODE_ENABLE: Consider DFS channels in ACS operation * @QCA_ACS_DFS_MODE_DISABLE: Do not consider DFS channels in ACS operation * @QCA_ACS_DFS_MODE_DEPRIORITIZE: Deprioritize DFS channels in ACS operation */ enum qca_acs_dfs_mode { QCA_ACS_DFS_MODE_NONE = 0, QCA_ACS_DFS_MODE_ENABLE = 1, QCA_ACS_DFS_MODE_DISABLE = 2, QCA_ACS_DFS_MODE_DEPRIORITIZE = 3, }; /** * enum qca_wlan_vendor_attr_acs_config - Defines Configuration attributes * used by the vendor command QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY. * * @QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE: Required (u8) * DFS mode for ACS operation from enum qca_acs_dfs_mode. * * @QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT: Required (u8) * channel number hint for ACS operation, if valid channel is specified then * ACS operation gives priority to this channel. * Note: If both the driver and user space application supports the 6 GHz band, * this attribute is deprecated and QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT * should be used. * To maintain backward compatibility, QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT * is still used if either of the driver or user space application doesn't * support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT: Required (u32). * Channel center frequency (MHz) hint for ACS operation, if a valid center * frequency is specified, ACS operation gives priority to this channel. */ enum qca_wlan_vendor_attr_acs_config { QCA_WLAN_VENDOR_ATTR_ACS_MODE_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MODE = 1, QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_HINT = 2, QCA_WLAN_VENDOR_ATTR_ACS_FREQUENCY_HINT = 3, QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ACS_DFS_MAX = QCA_WLAN_VENDOR_ATTR_ACS_DFS_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_get_hw_capability - Wi-Fi hardware capability */ enum qca_wlan_vendor_attr_get_hw_capability { QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_INVALID, /* Antenna isolation * An attribute used in the response. * The content of this attribute is encoded in a byte array. Each byte * value is an antenna isolation value. The array length is the number * of antennas. */ QCA_WLAN_VENDOR_ATTR_ANTENNA_ISOLATION, /* Request HW capability * An attribute used in the request. * The content of this attribute is a u32 array for one or more of * hardware capabilities (attribute IDs) that are being requested. Each * u32 value has a value from this * enum qca_wlan_vendor_attr_get_hw_capability * identifying which capabilities are requested. */ QCA_WLAN_VENDOR_ATTR_GET_HW_CAPABILITY, /* keep last */ QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_MAX = QCA_WLAN_VENDOR_ATTR_HW_CAPABILITY_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_ll_stats_ext - Attributes for MAC layer monitoring * offload which is an extension for LL_STATS. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD: Monitoring period. Unit in ms. * If MAC counters do not exceed the threshold, FW will report monitored * link layer counters periodically as this setting. The first report is * always triggered by this timer. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD: It is a percentage (1-99). * For each MAC layer counter, FW holds two copies. One is the current value. * The other is the last report. Once a current counter's increment is larger * than the threshold, FW will indicate that counter to host even if the * monitoring timer does not expire. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG: Peer STA power state change * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID: TID of MSDU * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU: Count of MSDU with the same * failure code. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS: TX failure code * 1: TX packet discarded * 2: No ACK * 3: Postpone * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS: peer MAC address * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE: Peer STA current state * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_GLOBAL: Global threshold. * Threshold for all monitored parameters. If per counter dedicated threshold * is not enabled, this threshold will take effect. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_EVENT_MODE: Indicate what triggers this * event, PERORID_TIMEOUT == 1, THRESH_EXCEED == 0. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_ID: interface ID * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ID: peer ID * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BITMAP: bitmap for TX counters * Bit0: TX counter unit in MSDU * Bit1: TX counter unit in MPDU * Bit2: TX counter unit in PPDU * Bit3: TX counter unit in byte * Bit4: Dropped MSDUs * Bit5: Dropped Bytes * Bit6: MPDU retry counter * Bit7: MPDU failure counter * Bit8: PPDU failure counter * Bit9: MPDU aggregation counter * Bit10: MCS counter for ACKed MPDUs * Bit11: MCS counter for Failed MPDUs * Bit12: TX Delay counter * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BITMAP: bitmap for RX counters * Bit0: MAC RX counter unit in MPDU * Bit1: MAC RX counter unit in byte * Bit2: PHY RX counter unit in PPDU * Bit3: PHY RX counter unit in byte * Bit4: Disorder counter * Bit5: Retry counter * Bit6: Duplication counter * Bit7: Discard counter * Bit8: MPDU aggregation size counter * Bit9: MCS counter * Bit10: Peer STA power state change (wake to sleep) counter * Bit11: Peer STA power save counter, total time in PS mode * Bit12: Probe request counter * Bit13: Other management frames counter * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS_BITMAP: bitmap for CCA * Bit0: Idle time * Bit1: TX time * Bit2: time RX in current bss * Bit3: Out of current bss time * Bit4: Wireless medium busy time * Bit5: RX in bad condition time * Bit6: TX in bad condition time * Bit7: time wlan card not available * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_SIGNAL_BITMAP: bitmap for signal * Bit0: Per channel SNR counter * Bit1: Per channel noise floor counter * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM: number of peers * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CHANNEL_NUM: number of channels * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_AC_RX_NUM: number of RX stats * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS: per channel BSS CCA stats * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER: container for per PEER stats * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MSDU: Number of total TX MSDUs * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MPDU: Number of total TX MPDUs * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_PPDU: Number of total TX PPDUs * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BYTES: bytes of TX data * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP: Number of dropped TX packets * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP_BYTES: Bytes dropped * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_RETRY: waiting time without an ACK * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_ACK: number of MPDU not-ACKed * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_BACK: number of PPDU not-ACKed * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR_NUM: * aggregation stats buffer length * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS_NUM: length of mcs stats * buffer for ACKed MPDUs. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS_NUM: length of mcs stats * buffer for failed MPDUs. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_DELAY_ARRAY_SIZE: * length of delay stats array. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR: TX aggregation stats * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS: MCS stats for ACKed MPDUs * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS: MCS stats for failed MPDUs * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DELAY: tx delay stats * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU: MPDUs received * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_BYTES: bytes received * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU: PPDU received * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU_BYTES: PPDU bytes received * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_LOST: packets lost * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_RETRY: number of RX packets * flagged as retransmissions * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DUP: number of RX packets * flagged as duplicated * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DISCARD: number of RX * packets discarded * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR_NUM: length of RX aggregation * stats buffer. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS_NUM: length of RX mcs * stats buffer. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS: RX mcs stats buffer * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR: aggregation stats buffer * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_TIMES: times STAs go to sleep * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_DURATION: STAs' total sleep time * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PROBE_REQ: number of probe * requests received * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MGMT: number of other mgmt * frames received * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IDLE_TIME: Percentage of idle time * there is no TX, nor RX, nor interference. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_TIME: percentage of time * transmitting packets. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_TIME: percentage of time * for receiving. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BUSY: percentage of time * interference detected. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BAD: percentage of time * receiving packets with errors. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BAD: percentage of time * TX no-ACK. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NO_AVAIL: percentage of time * the chip is unable to work in normal conditions. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IN_BSS_TIME: percentage of time * receiving packets in current BSS. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_OUT_BSS_TIME: percentage of time * receiving packets not in current BSS. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ANT_NUM: number of antennas * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_SIGNAL: * This is a container for per antenna signal stats. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_SNR: per antenna SNR value * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF: per antenna NF value * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON: RSSI of beacon * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON: SNR of beacon * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME: u64 * Absolute timestamp from 1970/1/1, unit in ms. After receiving the * message, user layer APP could call gettimeofday to get another * timestamp and calculate transfer delay for the message. * @QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME: u32 * Real period for this measurement, unit in us. */ enum qca_wlan_vendor_attr_ll_stats_ext { QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_INVALID = 0, /* Attributes for configurations */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_PERIOD, QCA_WLAN_VENDOR_ATTR_LL_STATS_CFG_THRESHOLD, /* Peer STA power state change */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_CHG, /* TX failure event */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TID, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NUM_MSDU, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_STATUS, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_STATE, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_MAC_ADDRESS, /* MAC counters */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_GLOBAL, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_EVENT_MODE, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_ID, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ID, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BITMAP, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BITMAP, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS_BITMAP, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_SIGNAL_BITMAP, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CHANNEL_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_CCA_BSS, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER, /* Sub-attributes for PEER_AC_TX */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MSDU, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_MPDU, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_PPDU, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BYTES, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DROP_BYTES, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_RETRY, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_ACK, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_NO_BACK, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_AGGR, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_SUCC_MCS, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_FAIL_MCS, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_DELAY_ARRAY_SIZE, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_DELAY, /* Sub-attributes for PEER_AC_RX */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_BYTES, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PPDU_BYTES, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_LOST, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_RETRY, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DUP, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MPDU_DISCARD, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MCS, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_AGGR, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_TIMES, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_PS_DURATION, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_PROBE_REQ, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_MGMT, /* Sub-attributes for CCA_BSS */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IDLE_TIME, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_TIME, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_TIME, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BUSY, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_RX_BAD, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_TX_BAD, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_NO_AVAIL, /* sub-attribute for BSS_RX_TIME */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IN_BSS_TIME, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_OUT_BSS_TIME, /* Sub-attributes for PEER_SIGNAL */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_ANT_NUM, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_PEER_SIGNAL, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_SNR, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_ANT_NF, /* Sub-attributes for IFACE_BSS */ QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_RSSI_BEACON, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_IFACE_SNR_BEACON, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_REPORT_TIME, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MEASUREMENT_TIME, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_MAX = QCA_WLAN_VENDOR_ATTR_LL_STATS_EXT_LAST - 1 }; /* Attributes for FTM commands and events */ /** * enum qca_wlan_vendor_attr_loc_capa - Indoor location capabilities * * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAGS: Various flags. See * enum qca_wlan_vendor_attr_loc_capa_flags. * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_SESSIONS: Maximum number * of measurement sessions that can run concurrently. * Default is one session (no session concurrency). * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_PEERS: The total number of unique * peers that are supported in running sessions. For example, * if the value is 8 and maximum number of sessions is 2, you can * have one session with 8 unique peers, or 2 sessions with 4 unique * peers each, and so on. * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_BURSTS_EXP: Maximum number * of bursts per peer, as an exponent (2^value). Default is 0, * meaning no multi-burst support. * @QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_MEAS_PER_BURST: Maximum number * of measurement exchanges allowed in a single burst. * @QCA_WLAN_VENDOR_ATTR_AOA_CAPA_SUPPORTED_TYPES: Supported AOA measurement * types. A bit mask (unsigned 32 bit value), each bit corresponds * to an AOA type as defined by enum qca_vendor_attr_aoa_type. */ enum qca_wlan_vendor_attr_loc_capa { QCA_WLAN_VENDOR_ATTR_LOC_CAPA_INVALID, QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAGS, QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_SESSIONS, QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_PEERS, QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_NUM_BURSTS_EXP, QCA_WLAN_VENDOR_ATTR_FTM_CAPA_MAX_MEAS_PER_BURST, QCA_WLAN_VENDOR_ATTR_AOA_CAPA_SUPPORTED_TYPES, /* keep last */ QCA_WLAN_VENDOR_ATTR_LOC_CAPA_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LOC_CAPA_MAX = QCA_WLAN_VENDOR_ATTR_LOC_CAPA_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_loc_capa_flags: Indoor location capability flags * * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_RESPONDER: Set if driver * can be configured as an FTM responder (for example, an AP that * services FTM requests). QCA_NL80211_VENDOR_SUBCMD_FTM_CFG_RESPONDER * will be supported if set. * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR: Set if driver * can run FTM sessions. QCA_NL80211_VENDOR_SUBCMD_FTM_START_SESSION * will be supported if set. * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP: Set if FTM responder * supports immediate (ASAP) response. * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA: Set if driver supports standalone * AOA measurement using QCA_NL80211_VENDOR_SUBCMD_AOA_MEAS. * @QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA_IN_FTM: Set if driver supports * requesting AOA measurements as part of an FTM session. */ enum qca_wlan_vendor_attr_loc_capa_flags { QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_RESPONDER = 1 << 0, QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_FTM_INITIATOR = 1 << 1, QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_ASAP = 1 << 2, QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA = 1 << 3, QCA_WLAN_VENDOR_ATTR_LOC_CAPA_FLAG_AOA_IN_FTM = 1 << 4, }; /** * enum qca_wlan_vendor_attr_ftm_peer_info: Information about * a single peer in a measurement session. * * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAC_ADDR: The MAC address of the peer. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAGS: Various flags related * to measurement. See enum qca_wlan_vendor_attr_ftm_peer_meas_flags. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS: Nested attribute of * FTM measurement parameters, as specified by IEEE P802.11-REVmc/D7.0 * 9.4.2.167. See enum qca_wlan_vendor_attr_ftm_meas_param for * list of supported attributes. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID: Initial token ID for * secure measurement. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD: Request AOA * measurement every bursts. If 0 or not specified, * AOA measurements will be disabled for this peer. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_FREQ: Frequency in MHz where * the measurement frames are exchanged. Optional; if not * specified, try to locate the peer in the kernel scan * results cache and use frequency from there. */ enum qca_wlan_vendor_attr_ftm_peer_info { QCA_WLAN_VENDOR_ATTR_FTM_PEER_INVALID, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAC_ADDR, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAGS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_PARAMS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID, QCA_WLAN_VENDOR_ATTR_FTM_PEER_AOA_BURST_PERIOD, QCA_WLAN_VENDOR_ATTR_FTM_PEER_FREQ, /* keep last */ QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MAX = QCA_WLAN_VENDOR_ATTR_FTM_PEER_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_ftm_peer_meas_flags: Measurement request flags, * per-peer * * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_ASAP: If set, request * immediate (ASAP) response from peer. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCI: If set, request * LCI report from peer. The LCI report includes the absolute * location of the peer in "official" coordinates (similar to GPS). * See IEEE P802.11-REVmc/D7.0, 11.24.6.7 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCR: If set, request * Location civic report from peer. The LCR includes the location * of the peer in free-form format. See IEEE P802.11-REVmc/D7.0, * 11.24.6.7 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_SECURE: If set, * request a secure measurement. * QCA_WLAN_VENDOR_ATTR_FTM_PEER_SECURE_TOKEN_ID must also be provided. */ enum qca_wlan_vendor_attr_ftm_peer_meas_flags { QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_ASAP = 1 << 0, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCI = 1 << 1, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_LCR = 1 << 2, QCA_WLAN_VENDOR_ATTR_FTM_PEER_MEAS_FLAG_SECURE = 1 << 3, }; /** * enum qca_wlan_vendor_attr_ftm_meas_param: Measurement parameters * * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MEAS_PER_BURST: Number of measurements * to perform in a single burst. * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_NUM_BURSTS_EXP: Number of bursts to * perform, specified as an exponent (2^value). * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION: Duration of burst * instance, as specified in IEEE P802.11-REVmc/D7.0, 9.4.2.167. * @QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_PERIOD: Time between bursts, * as specified in IEEE P802.11-REVmc/D7.0, 9.4.2.167. Must * be larger than QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION. */ enum qca_wlan_vendor_attr_ftm_meas_param { QCA_WLAN_VENDOR_ATTR_FTM_PARAM_INVALID, QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MEAS_PER_BURST, QCA_WLAN_VENDOR_ATTR_FTM_PARAM_NUM_BURSTS_EXP, QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_DURATION, QCA_WLAN_VENDOR_ATTR_FTM_PARAM_BURST_PERIOD, /* keep last */ QCA_WLAN_VENDOR_ATTR_FTM_PARAM_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_FTM_PARAM_MAX = QCA_WLAN_VENDOR_ATTR_FTM_PARAM_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_ftm_peer_result: Per-peer results * * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAC_ADDR: MAC address of the reported * peer. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS: Status of measurement * request for this peer. * See enum qca_wlan_vendor_attr_ftm_peer_result_status. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAGS: Various flags related * to measurement results for this peer. * See enum qca_wlan_vendor_attr_ftm_peer_result_flags. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS: Specified when * request failed and peer requested not to send an additional request * for this number of seconds. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCI: LCI report when received * from peer. In the format specified by IEEE P802.11-REVmc/D7.0, * 9.4.2.22.10. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCR: Location civic report when * received from peer. In the format specified by IEEE P802.11-REVmc/D7.0, * 9.4.2.22.13. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAMS: Reported when peer * overridden some measurement request parameters. See * enum qca_wlan_vendor_attr_ftm_meas_param. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AOA_MEAS: AOA measurement * for this peer. Same contents as @QCA_WLAN_VENDOR_ATTR_AOA_MEAS_RESULT. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS: Array of measurement * results. Each entry is a nested attribute defined * by enum qca_wlan_vendor_attr_ftm_meas. */ enum qca_wlan_vendor_attr_ftm_peer_result { QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_INVALID, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAC_ADDR, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAGS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCI, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_LCR, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAMS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AOA_MEAS, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS, /* keep last */ QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MAX = QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_ftm_peer_result_status * * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_OK: Request sent ok and results * will be provided. Peer may have overridden some measurement parameters, * in which case overridden parameters will be report by * QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_MEAS_PARAM attribute. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INCAPABLE: Peer is incapable * of performing the measurement request. No more results will be sent * for this peer in this session. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_FAILED: Peer reported request * failed, and requested not to send an additional request for number * of seconds specified by QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_VALUE_SECONDS * attribute. * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INVALID: Request validation * failed. Request was not sent over the air. */ enum qca_wlan_vendor_attr_ftm_peer_result_status { QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_OK, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INCAPABLE, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_FAILED, QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_STATUS_INVALID, }; /** * enum qca_wlan_vendor_attr_ftm_peer_result_flags: Various flags * for measurement result, per-peer * * @QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAG_DONE: If set, * measurement completed for this peer. No more results will be reported * for this peer in this session. */ enum qca_wlan_vendor_attr_ftm_peer_result_flags { QCA_WLAN_VENDOR_ATTR_FTM_PEER_RES_FLAG_DONE = 1 << 0, }; /** * enum qca_vendor_attr_loc_session_status: Session completion status code * * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_OK: Session completed * successfully. * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_ABORTED: Session aborted * by request. * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_INVALID: Session request * was invalid and was not started. * @QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_FAILED: Session had an error * and did not complete normally (for example out of resources). */ enum qca_vendor_attr_loc_session_status { QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_OK, QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_ABORTED, QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_INVALID, QCA_WLAN_VENDOR_ATTR_LOC_SESSION_STATUS_FAILED, }; /** * enum qca_wlan_vendor_attr_ftm_meas: Single measurement data * * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T1: Time of departure (TOD) of FTM packet as * recorded by responder, in picoseconds. * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T2: Time of arrival (TOA) of FTM packet at * initiator, in picoseconds. * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T3: TOD of ACK packet as recorded by * initiator, in picoseconds. * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T4: TOA of ACK packet at * responder, in picoseconds. * See IEEE P802.11-REVmc/D7.0, 11.24.6.4 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_RSSI: RSSI (signal level) as recorded * during this measurement exchange. Optional and will be provided if * the hardware can measure it. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOD_ERR: TOD error reported by * responder. Not always provided. * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOA_ERR: TOA error reported by * responder. Not always provided. * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOD_ERR: TOD error measured by * initiator. Not always provided. * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOA_ERR: TOA error measured by * initiator. Not always provided. * See IEEE P802.11-REVmc/D7.0, 9.6.8.33 for more information. * @QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PAD: Dummy attribute for padding. */ enum qca_wlan_vendor_attr_ftm_meas { QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INVALID, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T1, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T2, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T3, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_T4, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_RSSI, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOD_ERR, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_TOA_ERR, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOD_ERR, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_INITIATOR_TOA_ERR, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_PAD, /* keep last */ QCA_WLAN_VENDOR_ATTR_FTM_MEAS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_FTM_MEAS_MAX = QCA_WLAN_VENDOR_ATTR_FTM_MEAS_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_aoa_type - AOA measurement type * * @QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE: Phase of the strongest * CIR (channel impulse response) path for each antenna. * @QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP: Phase and amplitude * of the strongest CIR path for each antenna. */ enum qca_wlan_vendor_attr_aoa_type { QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE, QCA_WLAN_VENDOR_ATTR_AOA_TYPE_TOP_CIR_PHASE_AMP, QCA_WLAN_VENDOR_ATTR_AOA_TYPE_MAX }; /** * enum qca_wlan_vendor_attr_encryption_test - Attributes to * validate encryption engine * * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION: Flag attribute. * This will be included if the request is for decryption; if not included, * the request is treated as a request for encryption by default. * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER: Unsigned 32-bit value * indicating the key cipher suite. Takes same values as * NL80211_ATTR_KEY_CIPHER. * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID: Unsigned 8-bit value * Key Id to be used for encryption * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK: Array of 8-bit values. * Key (TK) to be used for encryption/decryption * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN: Array of 8-bit values. * Packet number to be specified for encryption/decryption * 6 bytes for TKIP/CCMP/GCMP. * @QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA: Array of 8-bit values * representing the 802.11 packet (header + payload + FCS) that * needs to be encrypted/decrypted. * Encrypted/decrypted response from the driver will also be sent * to userspace with the same attribute. */ enum qca_wlan_vendor_attr_encryption_test { QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_NEEDS_DECRYPTION, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_CIPHER, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_KEYID, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_TK, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_PN, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_DATA, /* keep last */ QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_MAX = QCA_WLAN_VENDOR_ATTR_ENCRYPTION_TEST_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_dmg_rf_sector_type - Type of * sector for DMG RF sector operations. * * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_RX: RX sector * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_TX: TX sector */ enum qca_wlan_vendor_attr_dmg_rf_sector_type { QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_RX, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_TX, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_TYPE_MAX }; /** * enum qca_wlan_vendor_attr_fw_state - State of firmware * * @QCA_WLAN_VENDOR_ATTR_FW_STATE_ERROR: FW is in bad state * @QCA_WLAN_VENDOR_ATTR_FW_STATE_ACTIVE: FW is active */ enum qca_wlan_vendor_attr_fw_state { QCA_WLAN_VENDOR_ATTR_FW_STATE_ERROR, QCA_WLAN_VENDOR_ATTR_FW_STATE_ACTIVE, QCA_WLAN_VENDOR_ATTR_FW_STATE_MAX }; /** * BRP antenna limit mode * * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE: Disable BRP force * antenna limit, BRP will be performed as usual. * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE: Define maximal * antennas limit. the hardware may use less antennas than the * maximum limit. * @QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE: The hardware will * use exactly the specified number of antennas for BRP. */ enum qca_wlan_vendor_attr_brp_ant_limit_mode { QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_DISABLE, QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_EFFECTIVE, QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_FORCE, QCA_WLAN_VENDOR_ATTR_BRP_ANT_LIMIT_MODE_MAX }; /** * enum qca_wlan_vendor_attr_dmg_rf_sector_cfg - Attributes for * DMG RF sector configuration for a single RF module. * The values are defined in a compact way which closely matches * the way it is stored in HW registers. * The configuration provides values for 32 antennas and 8 distribution * amplifiers, and together describes the characteristics of the RF * sector - such as a beam in some direction with some gain. * * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX: Index * of RF module for this configuration. * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE0: Bit 0 of edge * amplifier gain index. Unsigned 32 bit number containing * bits for all 32 antennas. * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE1: Bit 1 of edge * amplifier gain index. Unsigned 32 bit number containing * bits for all 32 antennas. * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE2: Bit 2 of edge * amplifier gain index. Unsigned 32 bit number containing * bits for all 32 antennas. * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_HI: Phase values * for first 16 antennas, 2 bits per antenna. * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_LO: Phase values * for last 16 antennas, 2 bits per antenna. * @QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16: Contains * DTYPE values (3 bits) for each distribution amplifier, followed * by X16 switch bits for each distribution amplifier. There are * total of 8 distribution amplifiers. */ enum qca_wlan_vendor_attr_dmg_rf_sector_cfg { QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_INVALID = 0, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MODULE_INDEX = 1, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE0 = 2, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE1 = 3, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_ETYPE2 = 4, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_HI = 5, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_PSH_LO = 6, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_DTYPE_X16 = 7, /* keep last */ QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_MAX = QCA_WLAN_VENDOR_ATTR_DMG_RF_SECTOR_CFG_AFTER_LAST - 1 }; enum qca_wlan_vendor_attr_ll_stats_set { QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_INVALID = 0, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD = 1, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_MAX = QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_ll_stats_clr { QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_INVALID = 0, /* Unsigned 32bit bitmap for clearing statistics * All radio statistics 0x00000001 * cca_busy_time (within radio statistics) 0x00000002 * All channel stats (within radio statistics) 0x00000004 * All scan statistics (within radio statistics) 0x00000008 * All interface statistics 0x00000010 * All tx rate statistics (within interface statistics) 0x00000020 * All ac statistics (with in interface statistics) 0x00000040 * All contention (min, max, avg) statistics (within ac statisctics) * 0x00000080. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK = 1, /* Unsigned 8 bit value: Request to stop statistics collection */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ = 2, /* Unsigned 32 bit bitmap: Response from the driver * for the cleared statistics */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK = 3, /* Unsigned 8 bit value: Response from driver/firmware * for the stop request */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX = QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_ll_stats_get { QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_INVALID = 0, /* Unsigned 32 bit value provided by the caller issuing the GET stats * command. When reporting the stats results, the driver uses the same * value to indicate which GET request the results correspond to. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID = 1, /* Unsigned 32 bit value - bit mask to identify what statistics are * requested for retrieval. * Radio Statistics 0x00000001 * Interface Statistics 0x00000020 * All Peer Statistics 0x00000040 * Peer Statistics 0x00000080 */ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_MAX = QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_ll_stats_results { QCA_WLAN_VENDOR_ATTR_LL_STATS_INVALID = 0, /* Unsigned 32bit value. Used by the driver; must match the request id * provided with the QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET command. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_REQ_ID = 1, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX = 2, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX = 3, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX = 4, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX = 5, /* Signed 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT = 6, /* Signed 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA = 7, /* Signed 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK = 8, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_* are * nested within the interface stats. */ /* Interface mode, e.g., STA, SOFTAP, IBSS, etc. * Type = enum wifi_interface_mode. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE = 9, /* Interface MAC address. An array of 6 Unsigned int8 */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR = 10, /* Type = enum wifi_connection_state, e.g., DISCONNECTED, * AUTHENTICATING, etc. valid for STA, CLI only. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE = 11, /* Type = enum wifi_roam_state. Roaming state, e.g., IDLE or ACTIVE */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING = 12, /* Unsigned 32 bit value. WIFI_CAPABILITY_XXX */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES = 13, /* NULL terminated SSID. An array of 33 Unsigned 8bit values */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID = 14, /* BSSID. An array of 6 unsigned 8 bit values */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID = 15, /* Country string advertised by AP. An array of 3 unsigned 8 bit * values. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR = 16, /* Country string for this association. An array of 3 unsigned 8 bit * values. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR = 17, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* could * be nested within the interface stats. */ /* Type = enum wifi_traffic_ac, e.g., V0, VI, BE and BK */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC = 18, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU = 19, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU = 20, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST = 21, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST = 22, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU = 23, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU = 24, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST = 25, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES = 26, /* Unsigned int 32 value corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT = 27, /* Unsigned int 32 values corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG = 28, /* Unsigned int 32 values corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN = 29, /* Unsigned int 32 values corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX = 30, /* Unsigned int 32 values corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG = 31, /* Unsigned int 32 values corresponding to respective AC */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES = 32, /* Unsigned 32 bit value. Number of peers */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS = 33, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* are * nested within the interface stats. */ /* Type = enum wifi_peer_type. Peer type, e.g., STA, AP, P2P GO etc. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE = 34, /* MAC addr corresponding to respective peer. An array of 6 unsigned * 8 bit values. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS = 35, /* Unsigned int 32 bit value representing capabilities corresponding * to respective peer. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES = 36, /* Unsigned 32 bit value. Number of rates */ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES = 37, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_* * are nested within the rate stat. */ /* Wi-Fi Rate - separate attributes defined for individual fields */ /* Unsigned int 8 bit value; 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE = 38, /* Unsigned int 8 bit value; 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS = 39, /* Unsigned int 8 bit value; 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW = 40, /* Unsigned int 8 bit value; OFDM/CCK rate code would be as per IEEE Std * in the units of 0.5 Mbps HT/VHT it would be MCS index */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX = 41, /* Unsigned 32 bit value. Bit rate in units of 100 kbps */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE = 42, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_STAT_* could be * nested within the peer info stats. */ /* Unsigned int 32 bit value. Number of successfully transmitted data * packets, i.e., with ACK received corresponding to the respective * rate. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU = 43, /* Unsigned int 32 bit value. Number of received data packets * corresponding to the respective rate. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU = 44, /* Unsigned int 32 bit value. Number of data packet losses, i.e., no ACK * received corresponding to the respective rate. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST = 45, /* Unsigned int 32 bit value. Total number of data packet retries for * the respective rate. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES = 46, /* Unsigned int 32 bit value. Total number of short data packet retries * for the respective rate. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT = 47, /* Unsigned int 32 bit value. Total number of long data packet retries * for the respective rate. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG = 48, QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID = 49, /* Unsigned 32 bit value. Total number of msecs the radio is awake * accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME = 50, /* Unsigned 32 bit value. Total number of msecs the radio is * transmitting accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME = 51, /* Unsigned 32 bit value. Total number of msecs the radio is in active * receive accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME = 52, /* Unsigned 32 bit value. Total number of msecs the radio is awake due * to all scan accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN = 53, /* Unsigned 32 bit value. Total number of msecs the radio is awake due * to NAN accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD = 54, /* Unsigned 32 bit value. Total number of msecs the radio is awake due * to GSCAN accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN = 55, /* Unsigned 32 bit value. Total number of msecs the radio is awake due * to roam scan accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN = 56, /* Unsigned 32 bit value. Total number of msecs the radio is awake due * to PNO scan accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN = 57, /* Unsigned 32 bit value. Total number of msecs the radio is awake due * to Hotspot 2.0 scans and GAS exchange accruing over time. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20 = 58, /* Unsigned 32 bit value. Number of channels. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS = 59, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* could * be nested within the channel stats. */ /* Type = enum wifi_channel_width. Channel width, e.g., 20, 40, 80 */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH = 60, /* Unsigned 32 bit value. Primary 20 MHz channel. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ = 61, /* Unsigned 32 bit value. Center frequency (MHz) first segment. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0 = 62, /* Unsigned 32 bit value. Center frequency (MHz) second segment. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1 = 63, /* Attributes of type QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* could be * nested within the radio stats. */ /* Unsigned int 32 bit value representing total number of msecs the * radio is awake on that channel accruing over time, corresponding to * the respective channel. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME = 64, /* Unsigned int 32 bit value representing total number of msecs the CCA * register is busy accruing over time corresponding to the respective * channel. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME = 65, QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS = 66, /* Signifies the nested list of channel attributes * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO = 67, /* Signifies the nested list of peer info attributes * QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_* */ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO = 68, /* Signifies the nested list of rate info attributes * QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_* */ QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO = 69, /* Signifies the nested list of wmm info attributes * QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_* */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO = 70, /* Unsigned 8 bit value. Used by the driver; if set to 1, it indicates * that more stats, e.g., peers or radio, are to follow in the next * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_*_RESULTS event. * Otherwise, it is set to 0. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RESULTS_MORE_DATA = 71, /* Unsigned 64 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET = 72, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED = 73, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED = 74, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME = 75, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE = 76, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS = 77, /* Number of msecs the radio spent in transmitting for each power level */ QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL = 78, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_SUCC_CNT = 79, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RTS_FAIL_CNT = 80, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_SUCC_CNT = 81, /* Unsigned 32 bit value */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_PPDU_FAIL_CNT = 82, /* Unsigned int 32 value. * Pending MSDUs corresponding to respective AC. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_PENDING_MSDU = 83, /* u32 value representing total time in milliseconds for which the radio * is transmitting on this channel. This attribute will be nested * within QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_TX_TIME = 84, /* u32 value representing total time in milliseconds for which the radio * is receiving all 802.11 frames intended for this device on this * channel. This attribute will be nested within * QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85, /* u8 value representing the channel load percentage. Possible values * are 0-100. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_LOAD_PERCENTAGE = 86, /* u8 value representing the time slicing duty cycle percentage. * Possible values are 0-100. */ QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_TS_DUTY_CYCLE = 87, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_ll_stats_type { QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID = 0, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO = 1, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE = 2, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS = 3, /* keep last */ QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_AFTER_LAST, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_MAX = QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_tdls_configuration - Attributes for * TDLS configuration to the host driver. * * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE: Configure the TDLS trigger * mode in the host driver. enum qca_wlan_vendor_tdls_trigger_mode * represents the different TDLS trigger modes. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD: Duration (u32) within * which QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD number * of packets shall meet the criteria for implicit TDLS setup. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD: Number (u32) of Tx/Rx packets * within a duration QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD * to initiate a TDLS setup. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD: Time (u32) to initiate * a TDLS Discovery to the peer. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT: Max number (u32) of * discovery attempts to know the TDLS capability of the peer. A peer is * marked as TDLS not capable if there is no response for all the attempts. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT: Represents a duration (u32) * within which QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD * number of TX / RX frames meet the criteria for TDLS teardown. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD: Minimum number (u32) * of Tx/Rx packets within a duration * QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT to tear down a TDLS link. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD: Threshold * corresponding to the RSSI of the peer below which a TDLS setup is * triggered. * @QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD: Threshold * corresponding to the RSSI of the peer above which a TDLS teardown is * triggered. */ enum qca_wlan_vendor_attr_tdls_configuration { QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE = 1, /* Attributes configuring the TDLS Implicit Trigger */ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_STATS_PERIOD = 2, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TX_THRESHOLD = 3, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_DISCOVERY_PERIOD = 4, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX_DISCOVERY_ATTEMPT = 5, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_TIMEOUT = 6, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IDLE_PACKET_THRESHOLD = 7, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_SETUP_RSSI_THRESHOLD = 8, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TEARDOWN_RSSI_THRESHOLD = 9, /* keep last */ QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_tdls_trigger_mode: Represents the TDLS trigger mode in * the driver * * The following are the different values for * QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_TRIGGER_MODE. * * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: The trigger to initiate/teardown * the TDLS connection to a respective peer comes from the user space. * wpa_supplicant provides the commands TDLS_SETUP, TDLS_TEARDOWN, * TDLS_DISCOVER to do this. * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: Host driver triggers this TDLS * setup/teardown to the eligible peer once the configured criteria * (such as TX/RX threshold, RSSI) is met. The attributes * in QCA_WLAN_VENDOR_ATTR_TDLS_CONFIG_IMPLICIT_PARAMS correspond to * the different configuration criteria for the TDLS trigger from the * host driver. * @QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: Enables the driver to trigger * the TDLS setup / teardown through the implicit mode only to the * configured MAC addresses (wpa_supplicant, with tdls_external_control=1, * configures the MAC address through TDLS_SETUP / TDLS_TEARDOWN commands). * External mode works on top of the implicit mode. Thus the host driver * is expected to configure in TDLS Implicit mode too to operate in * External mode. * Configuring External mode alone without Implicit mode is invalid. * * All the above implementations work as expected only when the host driver * advertises the capability WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP - representing * that the TDLS message exchange is not internal to the host driver, but * depends on wpa_supplicant to do the message exchange. */ enum qca_wlan_vendor_tdls_trigger_mode { QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT = 1 << 0, QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT = 1 << 1, QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL = 1 << 2, }; /** * enum qca_vendor_attr_sar_limits_selections - Source of SAR power limits * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0: Select SAR profile #0 * that is hard-coded in the Board Data File (BDF). * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1: Select SAR profile #1 * that is hard-coded in the Board Data File (BDF). * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2: Select SAR profile #2 * that is hard-coded in the Board Data File (BDF). * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3: Select SAR profile #3 * that is hard-coded in the Board Data File (BDF). * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4: Select SAR profile #4 * that is hard-coded in the Board Data File (BDF). * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE: Do not select any * source of SAR power limits, thereby disabling the SAR power * limit feature. * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER: Select the SAR power * limits configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR. * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0: Select the SAR power * limits version 2.0 configured by %QCA_NL80211_VENDOR_SUBCMD_SET_SAR. * * This enumerates the valid set of values that may be supplied for * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT in an instance of * the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor command or in * the response to an instance of the * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command. */ enum qca_vendor_attr_sar_limits_selections { QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF0 = 0, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF1 = 1, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF2 = 2, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF3 = 3, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_BDF4 = 4, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_NONE = 5, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER = 6, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0 = 7, }; /** * enum qca_vendor_attr_sar_limits_spec_modulations - * SAR limits specification modulation * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK - * CCK modulation * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM - * OFDM modulation * * This enumerates the valid set of values that may be supplied for * attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION in an * instance of attribute %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC in an * instance of the %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS vendor * command or in the response to an instance of the * %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS vendor command. */ enum qca_vendor_attr_sar_limits_spec_modulations { QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_CCK = 0, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION_OFDM = 1, }; /** * enum qca_vendor_attr_sar_limits - Attributes for SAR power limits * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE: Optional (u32) value to * select which SAR power limit table should be used. Valid * values are enumerated in enum * %qca_vendor_attr_sar_limits_selections. The existing SAR * power limit selection is unchanged if this attribute is not * present. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS: Optional (u32) value * which specifies the number of SAR power limit specifications * which will follow. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC: Nested array of SAR power * limit specifications. The number of specifications is * specified by @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS. Each * specification contains a set of * QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_* attributes. A * specification is uniquely identified by the attributes * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND, * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN, and * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION and always * contains as a payload the attribute * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT, * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX. * Either %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT or * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX is * needed based upon the value of * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND: Optional (u32) value to * indicate for which band this specification applies. Valid * values are enumerated in enum %nl80211_band (although not all * bands may be supported by a given device). If the attribute is * not supplied then the specification will be applied to all * supported bands. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN: Optional (u32) value * to indicate for which antenna chain this specification * applies, i.e. 1 for chain 1, 2 for chain 2, etc. If the * attribute is not supplied then the specification will be * applied to all chains. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION: Optional (u32) * value to indicate for which modulation scheme this * specification applies. Valid values are enumerated in enum * %qca_vendor_attr_sar_limits_spec_modulations. If the attribute * is not supplied then the specification will be applied to all * modulation schemes. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT: Required (u32) * value to specify the actual power limit value in units of 0.5 * dBm (i.e., a value of 11 represents 5.5 dBm). * This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_USER. * * @QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX: Required (u32) * value to indicate SAR V2 indices (0 - 11) to select SAR V2 profiles. * This is required, when %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT is * %QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SELECT_V2_0. * * These attributes are used with %QCA_NL80211_VENDOR_SUBCMD_SET_SAR_LIMITS * and %QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS. */ enum qca_vendor_attr_sar_limits { QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SAR_ENABLE = 1, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_NUM_SPECS = 2, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC = 3, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_BAND = 4, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_CHAIN = 5, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_MODULATION = 6, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT = 7, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_SPEC_POWER_LIMIT_INDEX = 8, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_MAX = QCA_WLAN_VENDOR_ATTR_SAR_LIMITS_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_get_wifi_info: Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO sub command. * * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION: In a request this attribute * should be set to any U8 value to indicate that the driver version * should be returned. When enabled in this manner, in a response this * attribute will contain a string representation of the driver version. * * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION: In a request this attribute * should be set to any U8 value to indicate that the firmware version * should be returned. When enabled in this manner, in a response this * attribute will contain a string representation of the firmware version. * * @QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX: In a request this attribute * should be set to any U32 value to indicate that the current radio * index should be returned. When enabled in this manner, in a response * this attribute will contain a U32 radio index value. * */ enum qca_wlan_vendor_attr_get_wifi_info { QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_INVALID = 0, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION = 1, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION = 2, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_RADIO_INDEX = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_AFTER_LAST - 1, }; /* * enum qca_wlan_vendor_attr_wifi_logger_start: Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START sub command. */ enum qca_wlan_vendor_attr_wifi_logger_start { QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_INVALID = 0, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID = 1, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL = 2, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_GET_MAX = QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_START_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_logger_results { QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_INVALID = 0, /* Unsigned 32-bit value; must match the request Id supplied by * Wi-Fi HAL in the corresponding subcmd NL msg. */ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_REQUEST_ID = 1, /* Unsigned 32-bit value; used to indicate the size of memory * dump to be allocated. */ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX = QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_AFTER_LAST - 1, }; /** * enum qca_scan_freq_list_type: Frequency list types * * @QCA_PREFERRED_SCAN_FREQ_LIST: The driver shall use the scan frequency list * specified with attribute QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST as * a preferred frequency list for roaming. * * @QCA_SPECIFIC_SCAN_FREQ_LIST: The driver shall use the frequency list * specified with attribute QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST as * a specific frequency list for roaming. */ enum qca_scan_freq_list_type { QCA_PREFERRED_SCAN_FREQ_LIST = 1, QCA_SPECIFIC_SCAN_FREQ_LIST = 2, }; /** * enum qca_vendor_attr_scan_freq_list_scheme: Frequency list scheme * * @QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST: Nested attribute of u32 values * List of frequencies in MHz to be considered for a roam scan. * * @QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE: Unsigned 32-bit value. * Type of frequency list scheme being configured/gotten as defined by the * enum qca_scan_freq_list_type. */ enum qca_vendor_attr_scan_freq_list_scheme { QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST = 1, QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_TYPE = 2, /* keep last */ QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST, QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_MAX = QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST - 1, }; /** * enum qca_roam_scan_scheme: Scan scheme * * @QCA_ROAM_SCAN_SCHEME_NO_SCAN: No frequencies specified to scan. * Indicates the driver to not scan on a Roam Trigger scenario, but * disconnect. E.g., on a BTM request from the AP the driver/firmware shall * disconnect from the current connected AP by notifying a failure * code in the BTM response. * * @QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN: Indicates the driver/firmware to * trigger partial frequency scans. These frequencies are the ones learned * or maintained by the driver based on the probability of finding the * BSSIDs in the ESS for which the roaming is triggered. * * @QCA_ROAM_SCAN_SCHEME_FULL_SCAN: Indicates the driver/firmware to * trigger the scan on all the valid frequencies to find better * candidates to roam. */ enum qca_roam_scan_scheme { QCA_ROAM_SCAN_SCHEME_NO_SCAN = 0, QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN = 1, QCA_ROAM_SCAN_SCHEME_FULL_SCAN = 2, }; /* * enum qca_vendor_roam_triggers: Bitmap of roaming triggers * * @QCA_ROAM_TRIGGER_REASON_PER: Set if the roam has to be triggered based on * a bad packet error rates (PER). * @QCA_ROAM_TRIGGER_REASON_BEACON_MISS: Set if the roam has to be triggered * based on beacon misses from the connected AP. * @QCA_ROAM_TRIGGER_REASON_POOR_RSSI: Set if the roam has to be triggered * due to poor RSSI of the connected AP. * @QCA_ROAM_TRIGGER_REASON_BETTER_RSSI: Set if the roam has to be triggered * upon finding a BSSID with a better RSSI than the connected BSSID. * Here the RSSI of the current BSSID need not be poor. * @QCA_ROAM_TRIGGER_REASON_PERIODIC: Set if the roam has to be triggered * by triggering a periodic scan to find a better AP to roam. * @QCA_ROAM_TRIGGER_REASON_DENSE: Set if the roam has to be triggered * when the connected channel environment is too noisy/congested. * @QCA_ROAM_TRIGGER_REASON_BTM: Set if the roam has to be triggered * when BTM Request frame is received from the connected AP. * @QCA_ROAM_TRIGGER_REASON_BSS_LOAD: Set if the roam has to be triggered * when the channel utilization is goes above the configured threshold. * @QCA_ROAM_TRIGGER_REASON_USER_TRIGGER: Set if the roam has to be triggered * based on the request from the user (space). * @QCA_ROAM_TRIGGER_REASON_DEAUTH: Set if the roam has to be triggered when * device receives Deauthentication/Disassociation frame from connected AP. * @QCA_ROAM_TRIGGER_REASON_IDLE: Set if the roam has to be triggered when the * device is in idle state (no TX/RX) and suspend mode, if the current RSSI * is determined to be a poor one. * @QCA_ROAM_TRIGGER_REASON_TX_FAILURES: Set if the roam has to be triggered * based on continuous TX Data frame failures to the connected AP. * @QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN: Set if the roam has to be triggered * based on the scan results obtained from an external scan (not triggered * to aim roaming). * * Set the corresponding roam trigger reason bit to consider it for roam * trigger. * Userspace can set multiple bits and send to the driver. The driver shall * consider all of them to trigger/initiate a roam scan. */ enum qca_vendor_roam_triggers { QCA_ROAM_TRIGGER_REASON_PER = 1 << 0, QCA_ROAM_TRIGGER_REASON_BEACON_MISS = 1 << 1, QCA_ROAM_TRIGGER_REASON_POOR_RSSI = 1 << 2, QCA_ROAM_TRIGGER_REASON_BETTER_RSSI = 1 << 3, QCA_ROAM_TRIGGER_REASON_PERIODIC = 1 << 4, QCA_ROAM_TRIGGER_REASON_DENSE = 1 << 5, QCA_ROAM_TRIGGER_REASON_BTM = 1 << 6, QCA_ROAM_TRIGGER_REASON_BSS_LOAD = 1 << 7, QCA_ROAM_TRIGGER_REASON_USER_TRIGGER = 1 << 8, QCA_ROAM_TRIGGER_REASON_DEAUTH = 1 << 9, QCA_ROAM_TRIGGER_REASON_IDLE = 1 << 10, QCA_ROAM_TRIGGER_REASON_TX_FAILURES = 1 << 11, QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN = 1 << 12, }; /* * enum qca_vendor_roam_fail_reasons: Defines the various roam * fail reasons. This enum value is used in * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON attribute. * * @QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED: Roam module in the firmware is not * able to trigger the scan. * @QCA_ROAM_FAIL_REASON_NO_AP_FOUND: No roamable APs found during roam scan. * @QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND: No candidate APs found during roam * scan. * @QCA_ROAM_FAIL_REASON_HOST: Roam fail due to disconnect issued from host. * @QCA_ROAM_FAIL_REASON_AUTH_SEND: Unable to send Authentication frame. * @QCA_ROAM_FAIL_REASON_AUTH_RECV: Received Authentication frame with error * status code. * @QCA_ROAM_FAIL_REASON_NO_AUTH_RESP: Authentication frame not received. * @QCA_ROAM_FAIL_REASON_REASSOC_SEND: Unable to send Reassociation Request * frame. * @QCA_ROAM_FAIL_REASON_REASSOC_RECV: Received Reassociation Response frame * with error status code. * @QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP: Reassociation Response frame not * received. * @QCA_ROAM_FAIL_REASON_SCAN_FAIL: Scan module not able to start scan. * @QCA_ROAM_FAIL_REASON_AUTH_NO_ACK: No ACK is received for Authentication * frame. * @QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP: Authentication frame is dropped * internally before transmission. * @QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK: No ACK is received for Reassociation * Request frame. * @QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP: Reassociation Request frame is * dropped internally. * @QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT: EAPOL-Key M1 is not received and * times out. * @QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND: Unable to send EAPOL-Key M2 frame. * @QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP: EAPOL-Key M2 frame dropped * internally. * @QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK: No ACK is received for EAPOL-Key * M2 frame. * @QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT: EAPOL-Key M3 frame is not received. * @QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND: Unable to send EAPOL-Key M4 frame. * @QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP: EAPOL-Key M4 frame dropped * internally. * @QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK: No ACK is received for EAPOL-Key M4 * frame. * @QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS: Roam scan is not * started for final beacon miss case. * @QCA_ROAM_FAIL_REASON_DISCONNECT: Deauthentication or Disassociation frame * received from the AP during roaming handoff. * @QCA_ROAM_FAIL_REASON_RESUME_ABORT: Firmware roams to the AP when the Apps * or host is suspended and gives the indication of the last roamed AP only * when the Apps is resumed. If the Apps is resumed while the roaming is in * progress, this ongoing roaming is aborted and the last roamed AP is * indicated to host. * @QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID: WPA3-SAE invalid PMKID. * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT: WPA3-SAE pre-authentication times * out. * @QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL: WPA3-SAE pre-authentication fails. */ enum qca_vendor_roam_fail_reasons { QCA_ROAM_FAIL_REASON_NONE = 0, QCA_ROAM_FAIL_REASON_SCAN_NOT_ALLOWED = 1, QCA_ROAM_FAIL_REASON_NO_AP_FOUND = 2, QCA_ROAM_FAIL_REASON_NO_CAND_AP_FOUND = 3, QCA_ROAM_FAIL_REASON_HOST = 4, QCA_ROAM_FAIL_REASON_AUTH_SEND = 5, QCA_ROAM_FAIL_REASON_AUTH_RECV = 6, QCA_ROAM_FAIL_REASON_NO_AUTH_RESP = 7, QCA_ROAM_FAIL_REASON_REASSOC_SEND = 8, QCA_ROAM_FAIL_REASON_REASSOC_RECV = 9, QCA_ROAM_FAIL_REASON_NO_REASSOC_RESP = 10, QCA_ROAM_FAIL_REASON_SCAN_FAIL = 11, QCA_ROAM_FAIL_REASON_AUTH_NO_ACK = 12, QCA_ROAM_FAIL_REASON_AUTH_INTERNAL_DROP = 13, QCA_ROAM_FAIL_REASON_REASSOC_NO_ACK = 14, QCA_ROAM_FAIL_REASON_REASSOC_INTERNAL_DROP = 15, QCA_ROAM_FAIL_REASON_EAPOL_M1_TIMEOUT = 16, QCA_ROAM_FAIL_REASON_EAPOL_M2_SEND = 17, QCA_ROAM_FAIL_REASON_EAPOL_M2_INTERNAL_DROP = 18, QCA_ROAM_FAIL_REASON_EAPOL_M2_NO_ACK = 19, QCA_ROAM_FAIL_REASON_EAPOL_M3_TIMEOUT = 20, QCA_ROAM_FAIL_REASON_EAPOL_M4_SEND = 21, QCA_ROAM_FAIL_REASON_EAPOL_M4_INTERNAL_DROP = 22, QCA_ROAM_FAIL_REASON_EAPOL_M4_NO_ACK = 23, QCA_ROAM_FAIL_REASON_NO_SCAN_FOR_FINAL_BEACON_MISS = 24, QCA_ROAM_FAIL_REASON_DISCONNECT = 25, QCA_ROAM_FAIL_REASON_RESUME_ABORT = 26, QCA_ROAM_FAIL_REASON_SAE_INVALID_PMKID = 27, QCA_ROAM_FAIL_REASON_SAE_PREAUTH_TIMEOUT = 28, QCA_ROAM_FAIL_REASON_SAE_PREAUTH_FAIL = 29, }; /* * enum qca_vendor_roam_invoke_fail_reasons: Defines the various roam * invoke fail reasons. This enum value is used in * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON attribute. * * @QCA_ROAM_INVOKE_STATUS_IFACE_INVALID: Invalid interface ID is passed * in roam invoke command. * @QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE: Roam offload in firmware is not * enabled. * @QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID: Connected AP profile SSID * length is invalid. * @QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW: Firmware internal roaming is already * in progress. * @QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP: Host sends the Beacon/Probe Response * of the AP in the roam invoke command to firmware. This reason is sent by the * firmware when the given AP is configured to be ignored or SSID/security * does not match. * @QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL: Roam handoff failed because of * firmware internal reasons. * @QCA_ROAM_INVOKE_STATUS_DISALLOW: Roam invoke trigger is not enabled. * @QCA_ROAM_INVOKE_STATUS_SCAN_FAIL: Scan start fail for roam invoke. * @QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL: Roam handoff start fail. * @QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS: Roam invoke parameters are invalid. * @QCA_ROAM_INVOKE_STATUS_NO_CAND_AP: No candidate AP found to roam to. * @QCA_ROAM_INVOKE_STATUS_ROAM_FAIL: Roam handoff failed. */ enum qca_vendor_roam_invoke_fail_reasons { QCA_ROAM_INVOKE_STATUS_NONE = 0, QCA_ROAM_INVOKE_STATUS_IFACE_INVALID = 1, QCA_ROAM_INVOKE_STATUS_OFFLOAD_DISABLE = 2, QCA_ROAM_INVOKE_STATUS_AP_SSID_LENGTH_INVALID = 3, QCA_ROAM_INVOKE_STATUS_ROAM_DISALLOW = 4, QCA_ROAM_INVOKE_STATUS_NON_ROAMABLE_AP = 5, QCA_ROAM_INVOKE_STATUS_ROAM_INTERNAL_FAIL = 6, QCA_ROAM_INVOKE_STATUS_DISALLOW = 7, QCA_ROAM_INVOKE_STATUS_SCAN_FAIL = 8, QCA_ROAM_INVOKE_STATUS_START_ROAM_FAIL = 9, QCA_ROAM_INVOKE_STATUS_INVALID_PARAMS = 10, QCA_ROAM_INVOKE_STATUS_NO_CAND_AP = 11, QCA_ROAM_INVOKE_STATUS_ROAM_FAIL = 12, }; /** * enum qca_vendor_attr_roam_candidate_selection_criteria: * * Each attribute carries a weightage in percentage (%). * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI: Unsigned 8-bit value. * Represents the weightage to be given for the RSSI selection * criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE: Unsigned 8-bit value. * Represents the weightage to be given for the rate selection * criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_BW: Unsigned 8-bit value. * Represents the weightage to be given for the band width selection * criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_BAND: Unsigned 8-bit value. * Represents the weightage to be given for the band selection * criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_NSS: Unsigned 8-bit value. * Represents the weightage to be given for the NSS selection * criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_CHAN_CONGESTION: Unsigned 8-bit value. * Represents the weightage to be given for the channel congestion * selection criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_BEAMFORMING: Unsigned 8-bit value. * Represents the weightage to be given for the beamforming selection * criteria among other parameters. * * @QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_OCE_WAN: Unsigned 8-bit value. * Represents the weightage to be given for the OCE selection * criteria among other parameters. */ enum qca_vendor_attr_roam_candidate_selection_criteria { QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_RSSI = 1, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE = 2, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_BW = 3, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_BAND = 4, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_NSS = 5, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_CHAN_CONGESTION = 6, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_BEAMFORMING = 7, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_SCORE_OCE_WAN = 8, /* keep last */ QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_AFTER_LAST, QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_MAX = QCA_ATTR_ROAM_CAND_SEL_CRITERIA_RATE_AFTER_LAST - 1, }; /** * enum qca_vendor_attr_roam_control - Attributes to carry roam configuration * The following attributes are used to set/get/clear the respective * configurations to/from the driver. * For the get, the attribute for the configuration to be queried shall * carry any of its acceptable values to the driver. In return, the driver * shall send the configured values within the same attribute to the user * space. * * @QCA_ATTR_ROAM_CONTROL_ENABLE: Unsigned 8-bit value. * Signifies to enable/disable roam control in driver. * 1-enable, 0-disable * Enable: Mandates the driver to do the further roams using the * configuration parameters set through * QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET. * Disable: Disables the driver/firmware roaming triggered through * QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET. Further roaming is * expected to continue with the default configurations. * * @QCA_ATTR_ROAM_CONTROL_STATUS: Unsigned 8-bit value. * This is used along with QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET. * Roam control status is obtained through this attribute. * * @QCA_ATTR_ROAM_CONTROL_CLEAR_ALL: Flag attribute to indicate the * complete config set through QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET * is to be cleared in the driver. * This is used along with QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR * and shall be ignored if used with other sub commands. * If this attribute is specified along with subcmd * QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR, the driver shall ignore * all other attributes, if there are any. * If this attribute is not specified when the subcmd * QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR is sent, the driver shall * clear the data corresponding to the attributes specified. * * @QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME: Nested attribute to carry the * list of frequencies and its type, represented by * enum qca_vendor_attr_scan_freq_list_scheme. * Frequency list and its type are mandatory for this attribute to set * the frequencies. * Frequency type is mandatory for this attribute to get the frequencies * and the frequency list is obtained through * QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST. * Frequency list type is mandatory for this attribute to clear the * frequencies. * * @QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD: Unsigned 32-bit value. * Carries the value of scan period in seconds to set. * The value of scan period is obtained with the same attribute for get. * Clears the scan period in the driver when specified with clear command. * Scan period is the idle time in seconds between each subsequent * channel scans. * * @QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD: Unsigned 32-bit value. * Carries the value of full scan period in seconds to set. * The value of full scan period is obtained with the same attribute for * get. * Clears the full scan period in the driver when specified with clear * command. Full scan period is the idle period in seconds between two * successive full channel roam scans. * * @QCA_ATTR_ROAM_CONTROL_TRIGGERS: Unsigned 32-bit value. * Carries a bitmap of the roam triggers specified in * enum qca_vendor_roam_triggers. * The driver shall enable roaming by enabling corresponding roam triggers * based on the trigger bits sent with this attribute. * If this attribute is not configured, the driver shall proceed with * default behavior. * The bitmap configured is obtained with the same attribute for get. * Clears the bitmap configured in driver when specified with clear * command. * * @QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA: Nested attribute signifying the * weightage in percentage (%) to be given for each selection criteria. * Different roam candidate selection criteria are represented by * enum qca_vendor_attr_roam_candidate_selection_criteria. * The driver shall select the roam candidate based on corresponding * candidate selection scores sent. * * An empty nested attribute is used to indicate that no specific * preference score/criteria is configured (i.e., to disable this mechanism * in the set case and to show that the mechanism is disabled in the get * case). * * Userspace can send multiple attributes out of this enum to the driver. * Since this attribute represents the weight/percentage of preference for * the respective selection criteria, it is preferred to configure 100% * total weightage. The value in each attribute or cumulative weight of the * values in all the nested attributes should not exceed 100%. The driver * shall reject such configuration. * * If the weights configured through this attribute are less than 100%, * the driver shall honor the weights (x%) passed for the corresponding * selection criteria and choose/distribute rest of the weight (100-x)% * for the other selection criteria, based on its internal logic. * * The selection criteria configured is obtained with the same * attribute for get. * * Clears the selection criteria configured in the driver when specified * with clear command. * * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME: Unsigned 32-bit value. * Represents value of the scan frequency scheme from enum * qca_roam_scan_scheme. * It's an optional attribute. If this attribute is not configured, the * driver shall proceed with default behavior. * * @QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD: Signed 32-bit value in dBm, * signifying the RSSI threshold of the current connected AP, indicating * the driver to trigger roam only when the current connected AP's RSSI * is less than this threshold. * * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm, * signifying the RSSI threshold of the candidate AP, indicating * the driver to trigger roam only to the candidate AP with RSSI * better than this threshold. If RSSI thresholds for candidate APs found * in the 2.4 GHz, 5 GHz, and 6 GHz bands are configured separately using * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ, * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ, and/or * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ, those values will * take precedence over the value configured using the * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute. * * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the * user defined reason code to be sent to the AP in response to AP's * request to trigger the roam if the roaming cannot be triggered. * Applies to all the scenarios of AP assisted roaming (e.g., BTM). * * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS: Unsigned 32-bit value. * Carries a bitmap of the roam triggers specified in * enum qca_vendor_roam_triggers. * Represents the roam triggers for which the specific scan scheme from * enum qca_roam_scan_scheme has to be applied. * It's an optional attribute. If this attribute is not configured, but * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is specified, the scan scheme * specified through QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is applicable for * all the roams. * If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the * driver shall proceed with the default behavior. * * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ: Signed 32-bit value * in dBm, signifying the RSSI threshold of the candidate AP found in the * 2.4 GHz band. The driver/firmware shall trigger roaming to the candidate * AP found in the 2.4 GHz band only if its RSSI value is better than this * threshold. Optional attribute. If this attribute is not included, the * threshold value specified by the * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used. * * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ: Signed 32-bit value in * dBm, signifying the RSSI threshold of the candidate AP found in the 5 * GHz band. The driver/firmware shall trigger roaming to the candidate AP * found in the 5 GHz band only if its RSSI value is better than this * threshold. Optional attribute. If this attribute is not included, the * threshold value specified by tge * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used. * * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ: Signed 32-bit value in * dBm, signifying the RSSI threshold of the candidate AP found in the 6 * GHz band. The driver/firmware shall trigger roaming to the candidate AP * found in the 6 GHz band only if its RSSI value is better than this * threshold. Optional attribute. If this attribute is not included, the * threshold value specified by the * QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD attribute shall be used. * * @QCA_ATTR_ROAM_CONTROL_BAND_MASK: Unsigned 32-bit value. * Carries bitmask value of bits from &enum qca_set_band and represents * all the bands in which roaming is allowed. The configuration is valid * until next disconnection. If this attribute is not present, the * existing configuration shall be used. By default, roaming is allowed on * all bands supported by the local device. When the value is set to * %QCA_SETBAND_AUTO, all supported bands shall be enabled. * * @QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME: u16 value in milliseconds. * Optional parameter. Scan dwell time for active channels in the 2.4/5 GHz * bands. If this attribute is not configured, the driver shall proceed * with default behavior. * * @QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME: u16 value in milliseconds. * Optional parameter. Scan dwell time for passive channels in the 5 GHz * band. If this attribute is not configured, the driver shall proceed with * default behavior. * * @QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME: u16 value in milliseconds. * Optional parameter. The minimum duration to stay on the connected AP * channel during the channel scanning. If this attribute is not * configured, the driver shall proceed with default behavior. * * @QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME: u16 value in milliseconds. * Optional parameter. The maximum duration for which the radio can scan * foreign channels consecutively without coming back to home channel. If * this attribute is not configured, the driver shall proceed with default * behavior. * * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME: u16 value in milliseconds. * Optional parameter. Scan dwell time for 6G Preferred Scanning Channels. * If this attribute is not configured, the driver shall proceed with * default behavior. * * @QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME: u16 value in milliseconds. * Optional parameter. Scan dwell time for 6G Non Preferred Scanning * Channels. If this attribute is not configured, the driver shall proceed * with default behavior. */ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_ENABLE = 1, QCA_ATTR_ROAM_CONTROL_STATUS = 2, QCA_ATTR_ROAM_CONTROL_CLEAR_ALL = 3, QCA_ATTR_ROAM_CONTROL_FREQ_LIST_SCHEME= 4, QCA_ATTR_ROAM_CONTROL_SCAN_PERIOD = 5, QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD = 6, QCA_ATTR_ROAM_CONTROL_TRIGGERS = 7, QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA = 8, QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME = 9, QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10, QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11, QCA_ATTR_ROAM_CONTROL_USER_REASON = 12, QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13, QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_2P4GHZ = 14, QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_5GHZ = 15, QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD_6GHZ = 16, QCA_ATTR_ROAM_CONTROL_BAND_MASK = 17, QCA_ATTR_ROAM_CONTROL_ACTIVE_CH_DWELL_TIME = 18, QCA_ATTR_ROAM_CONTROL_PASSIVE_CH_DWELL_TIME = 19, QCA_ATTR_ROAM_CONTROL_HOME_CHANNEL_TIME = 20, QCA_ATTR_ROAM_CONTROL_MAXIMUM_AWAY_TIME = 21, QCA_ATTR_ROAM_CONTROL_SCAN_6G_PSC_DWELL_TIME = 22, QCA_ATTR_ROAM_CONTROL_SCAN_6G_NON_PSC_DWELL_TIME = 23, /* keep last */ QCA_ATTR_ROAM_CONTROL_AFTER_LAST, QCA_ATTR_ROAM_CONTROL_MAX = QCA_ATTR_ROAM_CONTROL_AFTER_LAST - 1, }; /* * enum qca_wlan_vendor_attr_roaming_config_params: Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_ROAM sub command. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD: Unsigned 32-bit value. * Represents the different roam sub commands referred by * enum qca_wlan_vendor_roaming_subcmd. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID: Unsigned 32-bit value. * Represents the Request ID for the specific set of commands. * This also helps to map specific set of commands to the respective * ID / client. e.g., helps to identify the user entity configuring the * ignored BSSIDs and accordingly clear the respective ones with the * matching ID. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned * 32-bit value.Represents the number of whitelist SSIDs configured. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST: Nested attribute * to carry the list of Whitelist SSIDs. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID: SSID (binary attribute, * 0..32 octets). Represents the white list SSID. Whitelist SSIDs * represent the list of SSIDs to which the firmware/driver can consider * to roam to. * * The following PARAM_A_BAND_XX attributes are applied to 5GHz BSSIDs when * comparing with a 2.4GHz BSSID. They are not applied when comparing two * 5GHz BSSIDs.The following attributes are set through the Roaming SUBCMD - * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD: Signed 32-bit * value, RSSI threshold above which 5GHz RSSI is favored. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD: Signed 32-bit * value, RSSI threshold below which 5GHz RSSI is penalized. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR: Unsigned 32-bit * value, factor by which 5GHz RSSI is boosted. * boost=(RSSI_measured-5GHz_boost_threshold)*5GHz_boost_factor * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR: Unsigned 32-bit * value, factor by which 5GHz RSSI is penalized. * penalty=(5GHz_penalty_threshold-RSSI_measured)*5GHz_penalty_factor * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST: Unsigned 32-bit * value, maximum boost that can be applied to a 5GHz RSSI. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS: Unsigned 32-bit * value, boost applied to current BSSID to ensure the currently * associated BSSID is favored so as to prevent ping-pong situations. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER: Signed 32-bit * value, RSSI below which "Alert" roam is enabled. * "Alert" mode roaming - firmware is "urgently" hunting for another BSSID * because the RSSI is low, or because many successive beacons have been * lost or other bad link conditions. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE: Unsigned 32-bit * value. 1-Enable, 0-Disable. Represents "Lazy" mode, where * firmware is hunting for a better BSSID or white listed SSID even though * the RSSI of the link is good. The parameters enabling the roaming are * configured through the PARAM_A_BAND_XX attrbutes. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS: Nested attribute, * represents the BSSIDs preferred over others while evaluating them * for the roaming. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID: Unsigned * 32-bit value. Represents the number of preferred BSSIDs set. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID: 6-byte MAC * address representing the BSSID to be preferred. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER: Signed * 32-bit value, representing the modifier to be applied to the RSSI of * the BSSID for the purpose of comparing it with other roam candidate. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS: Nested attribute, * represents the BSSIDs to get ignored for roaming. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID: Unsigned * 32-bit value, represents the number of ignored BSSIDs. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID: 6-byte MAC * address representing the ignored BSSID. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT: Flag attribute, * indicates this request to ignore the BSSID as a hint to the driver. The * driver can select this BSSID in the worst case (when no other BSSIDs are * better). * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL: Nested attribute to * set/get/clear the roam control config as * defined @enum qca_vendor_attr_roam_control. */ enum qca_wlan_vendor_attr_roaming_config_params { QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD = 1, QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID = 2, /* Attributes for wifi_set_ssid_white_list */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS = 3, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST = 4, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID = 5, /* Attributes for set_roam_params */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_THRESHOLD = 6, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_THRESHOLD = 7, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_BOOST_FACTOR = 8, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_PENALTY_FACTOR = 9, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_A_BAND_MAX_BOOST = 10, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_LAZY_ROAM_HISTERESYS = 11, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_ALERT_ROAM_RSSI_TRIGGER = 12, /* Attribute for set_lazy_roam */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE = 13, /* Attribute for set_lazy_roam with preferences */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS = 14, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_NUM_BSSID = 15, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID = 16, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER = 17, /* Attribute for setting ignored BSSID parameters */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, /* Flag attribute indicates this entry as a hint */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT = 21, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL = 22, /* keep last */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_MAX = QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_AFTER_LAST - 1, }; /* * enum qca_wlan_vendor_roaming_subcmd: Referred by * QCA_WLAN_VENDOR_ATTR_ROAMING_SUBCMD. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST: Sub command to * configure the white list SSIDs. These are configured through * the following attributes. * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS, * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_LIST, * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS: Sub command to * configure the Roam params. These parameters are evaluated on the GScan * results. Refers the attributes PARAM_A_BAND_XX above to configure the * params. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM: Sets the Lazy roam. Uses * the attribute QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_ENABLE * to enable/disable Lazy roam. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS: Sets the BSSID * preference. Contains the attribute * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID * preference. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs * to ignore in roaming decision. Uses * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET: Command to set the * roam control config to the driver with the attribute * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET: Command to obtain the * roam control config from driver with the attribute * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL. * For the get, the attribute for the configuration to be queried shall * carry any of its acceptable value to the driver. In return, the driver * shall send the configured values within the same attribute to the user * space. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR: Command to clear the * roam control config in the driver with the attribute * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL. * The driver shall continue with its default roaming behavior when data * corresponding to an attribute is cleared. */ enum qca_wlan_vendor_roaming_subcmd { QCA_WLAN_VENDOR_ROAMING_SUBCMD_INVALID = 0, QCA_WLAN_VENDOR_ROAMING_SUBCMD_SSID_WHITE_LIST = 1, QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_GSCAN_ROAM_PARAMS = 2, QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_LAZY_ROAM = 3, QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PREFS = 4, QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BSSID_PARAMS = 5, QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID = 6, QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET = 7, QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_GET = 8, QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_CLEAR = 9, }; enum qca_wlan_vendor_attr_gscan_config_params { QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_INVALID = 0, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID = 1, /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS sub command. */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND = 2, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS = 3, /* Attributes for input params used by * QCA_NL80211_VENDOR_SUBCMD_GSCAN_START sub command. */ /* Unsigned 32-bit value; channel frequency */ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL = 4, /* Unsigned 32-bit value; dwell time in ms. */ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME = 5, /* Unsigned 8-bit value; 0: active; 1: passive; N/A for DFS */ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE = 6, /* Unsigned 8-bit value; channel class */ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CLASS = 7, /* Unsigned 8-bit value; bucket index, 0 based */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX = 8, /* Unsigned 8-bit value; band. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND = 9, /* Unsigned 32-bit value; desired period, in ms. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD = 10, /* Unsigned 8-bit value; report events semantics. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS = 11, /* Unsigned 32-bit value. Followed by a nested array of * GSCAN_CHANNEL_SPEC_* attributes. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS = 12, /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_* attributes. * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS */ QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC = 13, /* Unsigned 32-bit value; base timer period in ms. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD = 14, /* Unsigned 32-bit value; number of APs to store in each scan in the * BSSID/RSSI history buffer (keep the highest RSSI APs). */ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN = 15, /* Unsigned 8-bit value; in %, when scan buffer is this much full, wake * up AP. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT = 16, /* Unsigned 8-bit value; number of scan bucket specs; followed by a * nested array of_GSCAN_BUCKET_SPEC_* attributes and values. The size * of the array is determined by NUM_BUCKETS. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS = 17, /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_* attributes. * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC = 18, /* Unsigned 8-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH = 19, /* Unsigned 32-bit value; maximum number of results to be returned. */ QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX = 20, /* An array of 6 x unsigned 8-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID = 21, /* Signed 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW = 22, /* Signed 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH = 23, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_CHANNEL = 24, /* Number of hotlist APs as unsigned 32-bit value, followed by a nested * array of AP_THRESHOLD_PARAM attributes and values. The size of the * array is determined by NUM_AP. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP = 25, /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_* attributes. * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS */ QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM = 26, /* Unsigned 32-bit value; number of samples for averaging RSSI. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE = 27, /* Unsigned 32-bit value; number of samples to confirm AP loss. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE = 28, /* Unsigned 32-bit value; number of APs breaching threshold. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING = 29, /* Unsigned 32-bit value; number of APs. Followed by an array of * AP_THRESHOLD_PARAM attributes. Size of the array is NUM_AP. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP = 30, /* Unsigned 32-bit value; number of samples to confirm AP loss. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE = 31, /* Unsigned 32-bit value. If max_period is non zero or different than * period, then this bucket is an exponential backoff bucket. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD = 32, /* Unsigned 32-bit value. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BASE = 33, /* Unsigned 32-bit value. For exponential back off bucket, number of * scans to perform for a given period. */ QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT = 34, /* Unsigned 8-bit value; in number of scans, wake up AP after these * many scans. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS = 35, /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST sub command. */ /* Unsigned 3-2bit value; number of samples to confirm SSID loss. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_LOST_SSID_SAMPLE_SIZE = 36, /* Number of hotlist SSIDs as unsigned 32-bit value, followed by a * nested array of SSID_THRESHOLD_PARAM_* attributes and values. The * size of the array is determined by NUM_SSID. */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID = 37, /* Array of QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_* * attributes. * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_HOTLIST_PARAMS_NUM_SSID */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM = 38, /* An array of 33 x unsigned 8-bit value; NULL terminated SSID */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_SSID = 39, /* Unsigned 8-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_BAND = 40, /* Signed 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_LOW = 41, /* Signed 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_SSID_THRESHOLD_PARAM_RSSI_HIGH = 42, /* Unsigned 32-bit value; a bitmask with additional gscan config flag. */ QCA_WLAN_VENDOR_ATTR_GSCAN_CONFIGURATION_FLAGS = 43, /* keep last */ QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_MAX = QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_gscan_results { QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_INVALID = 0, /* Unsigned 32-bit value; must match the request Id supplied by * Wi-Fi HAL in the corresponding subcmd NL msg. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID = 1, /* Unsigned 32-bit value; used to indicate the status response from * firmware/driver for the vendor sub-command. */ QCA_WLAN_VENDOR_ATTR_GSCAN_STATUS = 2, /* GSCAN Valid Channels attributes */ /* Unsigned 32bit value; followed by a nested array of CHANNELS. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS = 3, /* An array of NUM_CHANNELS x unsigned 32-bit value integers * representing channel numbers. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS = 4, /* GSCAN Capabilities attributes */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE = 5, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS = 6, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN = 7, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE = 8, /* Signed 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD = 9, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS = 10, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS = 11, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES = 12, /* GSCAN Attributes used with * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE sub-command. */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE = 13, /* GSCAN attributes used with * QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT sub-command. */ /* An array of NUM_RESULTS_AVAILABLE x * QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_* */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST = 14, /* Unsigned 64-bit value; age of sample at the time of retrieval */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP = 15, /* 33 x unsigned 8-bit value; NULL terminated SSID */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID = 16, /* An array of 6 x unsigned 8-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID = 17, /* Unsigned 32-bit value; channel frequency in MHz */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL = 18, /* Signed 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI = 19, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT = 20, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD = 21, /* Unsigned 16-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD = 22, /* Unsigned 16-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY = 23, /* Unsigned 32-bit value; size of the IE DATA blob */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH = 24, /* An array of IE_LENGTH x unsigned 8-bit value; blob of all the * information elements found in the beacon; this data should be a * packed list of wifi_information_element objects, one after the * other. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA = 25, /* Unsigned 8-bit value; set by driver to indicate more scan results are * available. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA = 26, /* GSCAN attributes for * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT sub-command. */ /* Unsigned 8-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE = 27, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS = 28, /* GSCAN attributes for * QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND sub-command. */ /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE * to indicate number of results. * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the * list of results. */ /* GSCAN attributes for * QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE sub-command. */ /* An array of 6 x unsigned 8-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID = 29, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL = 30, /* Unsigned 32-bit value. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI = 31, /* A nested array of signed 32-bit RSSI values. Size of the array is * determined by (NUM_RSSI of SIGNIFICANT_CHANGE_RESULT_NUM_RSSI. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST = 32, /* GSCAN attributes used with * QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS sub-command. */ /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE * to indicate number of gscan cached results returned. * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST to indicate * the list of gscan cached results. */ /* An array of NUM_RESULTS_AVAILABLE x * QCA_NL80211_VENDOR_ATTR_GSCAN_CACHED_RESULTS_* */ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST = 33, /* Unsigned 32-bit value; a unique identifier for the scan unit. */ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID = 34, /* Unsigned 32-bit value; a bitmask w/additional information about scan. */ QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS = 35, /* Use attr QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE * to indicate number of wifi scan results/bssids retrieved by the scan. * Also, use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the * list of wifi scan results returned for each cached result block. */ /* GSCAN attributes for * QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND sub-command. */ /* Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE for * number of results. * Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the nested * list of wifi scan results returned for each * wifi_passpoint_match_result block. * Array size: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE. */ /* GSCAN attributes for * QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND sub-command. */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES = 36, /* A nested array of * QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_* * attributes. Array size = * *_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_NETWORK_FOUND_NUM_MATCHES. */ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST = 37, /* Unsigned 32-bit value; network block id for the matched network */ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID = 38, /* Use QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST to indicate the nested * list of wifi scan results returned for each * wifi_passpoint_match_result block. */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN = 39, /* An array size of PASSPOINT_MATCH_ANQP_LEN of unsigned 8-bit values; * ANQP data in the information_element format. */ QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP = 40, /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS = 41, /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS = 42, /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID = 43, /* Unsigned 32-bit value; a GSCAN Capabilities attribute. */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID = 44, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED = 45, /* Unsigned 32-bit value; a GSCAN Capabilities attribute. * This is used to limit the maximum number of BSSIDs while sending * the vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM with subcmd * QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID and attribute * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID. */ QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID = 46, /* keep last */ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX = QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_AFTER_LAST - 1, }; enum qca_wlan_vendor_attr_pno_config_params { QCA_WLAN_VENDOR_ATTR_PNO_INVALID = 0, /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST sub command. */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM = 1, /* Array of nested QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_* * attributes. Array size = * QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM. */ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY = 2, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID = 3, /* An array of 256 x unsigned 8-bit value; NULL terminated UTF-8 encoded * realm, 0 if unspecified. */ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM = 4, /* An array of 16 x unsigned 32-bit value; roaming consortium ids to * match, 0 if unspecified. */ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID = 5, /* An array of 6 x unsigned 8-bit value; MCC/MNC combination, 0s if * unspecified. */ QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN = 6, /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST sub command. */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS = 7, /* Array of nested * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_* * attributes. Array size = * QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS. */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST = 8, /* An array of 33 x unsigned 8-bit value; NULL terminated SSID */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID = 9, /* Signed 8-bit value; threshold for considering this SSID as found, * required granularity for this threshold is 4 dBm to 8 dBm. */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_RSSI_THRESHOLD = 10, /* Unsigned 8-bit value; WIFI_PNO_FLAG_XXX */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS = 11, /* Unsigned 8-bit value; auth bit field for matching WPA IE */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT = 12, /* Unsigned 8-bit to indicate ePNO type; * It takes values from qca_wlan_epno_type */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_TYPE = 13, /* Nested attribute to send the channel list */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_CHANNEL_LIST = 14, /* Unsigned 32-bit value; indicates the interval between PNO scan * cycles in msec. */ QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_SCAN_INTERVAL = 15, QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI = 16, QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI = 17, QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX = 18, QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS = 19, QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS = 20, QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS = 21, QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS = 22, /* Unsigned 32-bit value, representing the PNO Request ID */ QCA_WLAN_VENDOR_ATTR_PNO_CONFIG_REQUEST_ID = 23, /* keep last */ QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_PNO_MAX = QCA_WLAN_VENDOR_ATTR_PNO_AFTER_LAST - 1, }; /** * qca_wlan_vendor_acs_select_reason: This represents the different reasons why * the ACS has to be triggered. These values are used by * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON and * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON */ enum qca_wlan_vendor_acs_select_reason { /* Represents the reason that the ACS triggered during the AP start */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_INIT, /* Represents the reason that DFS found with the current channel */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_DFS, /* Represents the reason that LTE co-exist in the current band. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_LTE_COEX, /* Represents the reason that generic, uncategorized interference has * been found in the current channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_GENERIC_INTERFERENCE, /* Represents the reason that excessive 802.11 interference has been * found in the current channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_80211_INTERFERENCE, /* Represents the reason that generic Continuous Wave (CW) interference * has been found in the current channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_CW_INTERFERENCE, /* Represents the reason that Microwave Oven (MWO) interference has been * found in the current channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_MWO_INTERFERENCE, /* Represents the reason that generic Frequency-Hopping Spread Spectrum * (FHSS) interference has been found in the current channel. This may * include 802.11 waveforms. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_FHSS_INTERFERENCE, /* Represents the reason that non-802.11 generic Frequency-Hopping * Spread Spectrum (FHSS) interference has been found in the current * channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_NON_80211_FHSS_INTERFERENCE, /* Represents the reason that generic Wideband (WB) interference has * been found in the current channel. This may include 802.11 waveforms. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_WB_INTERFERENCE, /* Represents the reason that non-802.11 generic Wideband (WB) * interference has been found in the current channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_NON_80211_WB_INTERFERENCE, /* Represents the reason that Jammer interference has been found in the * current channel. */ QCA_WLAN_VENDOR_ACS_SELECT_REASON_JAMMER_INTERFERENCE, }; /** * qca_wlan_vendor_attr_external_acs_policy: Attribute values for * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY to the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This represents the * external ACS policies to select the channels w.r.t. the PCL weights. * (QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL represents the channels and * their PCL weights.) * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY: Mandatory to * select a channel with non-zero PCL weight. * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED: Prefer a * channel with non-zero PCL weight. * */ enum qca_wlan_vendor_attr_external_acs_policy { QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_PREFERRED, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_POLICY_PCL_MANDATORY, }; /** * qca_wlan_vendor_channel_prop_flags: This represent the flags for a channel. * This is used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS. */ enum qca_wlan_vendor_channel_prop_flags { /* Bits 0, 1, 2, and 3 are reserved */ /* Turbo channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_TURBO = 1 << 4, /* CCK channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_CCK = 1 << 5, /* OFDM channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_OFDM = 1 << 6, /* 2.4 GHz spectrum channel. */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_2GHZ = 1 << 7, /* 5 GHz spectrum channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_5GHZ = 1 << 8, /* Only passive scan allowed */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_PASSIVE = 1 << 9, /* Dynamic CCK-OFDM channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_DYN = 1 << 10, /* GFSK channel (FHSS PHY) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_GFSK = 1 << 11, /* Radar found on channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_RADAR = 1 << 12, /* 11a static turbo channel only */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_STURBO = 1 << 13, /* Half rate channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HALF = 1 << 14, /* Quarter rate channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_QUARTER = 1 << 15, /* HT 20 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT20 = 1 << 16, /* HT 40 with extension channel above */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40PLUS = 1 << 17, /* HT 40 with extension channel below */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40MINUS = 1 << 18, /* HT 40 intolerant */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOL = 1 << 19, /* VHT 20 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT20 = 1 << 20, /* VHT 40 with extension channel above */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40PLUS = 1 << 21, /* VHT 40 with extension channel below */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT40MINUS = 1 << 22, /* VHT 80 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80 = 1 << 23, /* HT 40 intolerant mark bit for ACS use */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HT40INTOLMARK = 1 << 24, /* Channel temporarily blocked due to noise */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_BLOCKED = 1 << 25, /* VHT 160 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT160 = 1 << 26, /* VHT 80+80 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_VHT80_80 = 1 << 27, /* HE 20 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE20 = 1 << 28, /* HE 40 with extension channel above */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40PLUS = 1 << 29, /* HE 40 with extension channel below */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40MINUS = 1 << 30, /* HE 40 intolerant */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOL = 1 << 31, }; /** * qca_wlan_vendor_channel_prop_flags_2: This represents the flags for a * channel, and is a continuation of qca_wlan_vendor_channel_prop_flags. This is * used by QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2. */ enum qca_wlan_vendor_channel_prop_flags_2 { /* HE 40 intolerant mark bit for ACS use */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE40INTOLMARK = 1 << 0, /* HE 80 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80 = 1 << 1, /* HE 160 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE160 = 1 << 2, /* HE 80+80 channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_HE80_80 = 1 << 3, }; /** * qca_wlan_vendor_channel_prop_flags_ext: This represent the extended flags for * each channel. This is used by * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT. */ enum qca_wlan_vendor_channel_prop_flags_ext { /* Radar found on channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_RADAR_FOUND = 1 << 0, /* DFS required on channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS = 1 << 1, /* DFS required on channel for 2nd band of 80+80 */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CFREQ2 = 1 << 2, /* If channel has been checked for DFS */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DFS_CLEAR = 1 << 3, /* Excluded in 802.11d */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_11D_EXCLUDED = 1 << 4, /* Channel Switch Announcement received on this channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CSA_RECEIVED = 1 << 5, /* Ad-hoc is not allowed */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_ADHOC = 1 << 6, /* Station only channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_HOSTAP = 1 << 7, /* DFS radar history for client device (STA mode) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_HISTORY_RADAR = 1 << 8, /* DFS CAC valid for client device (STA mode) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID = 1 << 9, }; /** * qca_wlan_vendor_external_acs_event_chan_info_attr: Represents per channel * information. These attributes are sent as part of * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO. Each set of the following * attributes correspond to a single channel. */ enum qca_wlan_vendor_external_acs_event_chan_info_attr { QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_INVALID = 0, /* A bitmask (u32) with flags specified in * enum qca_wlan_vendor_channel_prop_flags. */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS = 1, /* A bitmask (u32) with flags specified in * enum qca_wlan_vendor_channel_prop_flags_ext. */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAG_EXT = 2, /* frequency in MHz (u32) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ = 3, /* maximum regulatory transmission power (u32) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_REG_POWER = 4, /* maximum transmission power (u32) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX_POWER = 5, /* minimum transmission power (u32) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MIN_POWER = 6, /* regulatory class id (u8) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_REG_CLASS_ID = 7, /* maximum antenna gain in (u8) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_ANTENNA_GAIN = 8, /* VHT segment 0 (u8) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 = 9, /* VHT segment 1 (u8) */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 = 10, /* A bitmask (u32) with flags specified in * enum qca_wlan_vendor_channel_prop_flags_2. */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FLAGS_2 = 11, /* * VHT segment 0 in MHz (u32) and the attribute is mandatory. * Note: Event QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS includes * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 * along with * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0. * * If both the driver and user-space application supports the 6 GHz * band, QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_0 * is deprecated and * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 * should be used. * * To maintain backward compatibility, * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 * is still used if either of the driver or user space application * doesn't support the 6 GHz band. */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_0 = 12, /* * VHT segment 1 in MHz (u32) and the attribute is mandatory. * Note: Event QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS includes * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 * along with * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1. * * If both the driver and user-space application supports the 6 GHz * band, QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_VHT_SEG_1 * is deprecated and * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 * should be considered. * * To maintain backward compatibility, * QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 * is still used if either of the driver or user space application * doesn't support the 6 GHz band. */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_FREQ_VHT_SEG_1 = 13, /* keep last */ QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST, QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_MAX = QCA_WLAN_VENDOR_EXTERNAL_ACS_EVENT_CHAN_INFO_ATTR_LAST - 1, }; /** * qca_wlan_vendor_attr_pcl: Represents attributes for * preferred channel list (PCL). These attributes are sent as part of * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL and * QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST. */ enum qca_wlan_vendor_attr_pcl { QCA_WLAN_VENDOR_ATTR_PCL_INVALID = 0, /* Channel number (u8) */ QCA_WLAN_VENDOR_ATTR_PCL_CHANNEL = 1, /* Channel weightage (u8) */ QCA_WLAN_VENDOR_ATTR_PCL_WEIGHT = 2, /* Channel frequency (u32) in MHz */ QCA_WLAN_VENDOR_ATTR_PCL_FREQ = 3, /* Channel flags (u32) * bit 0 set: channel to be used for GO role, * bit 1 set: channel to be used on CLI role, * bit 2 set: channel must be considered for operating channel * selection & peer chosen operating channel should be * one of the channels with this flag set, * bit 3 set: channel should be excluded in GO negotiation */ QCA_WLAN_VENDOR_ATTR_PCL_FLAG = 4, }; /** * qca_wlan_vendor_attr_external_acs_event: Attribute to vendor sub-command * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This attribute will be sent by * host driver. */ enum qca_wlan_vendor_attr_external_acs_event { QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_INVALID = 0, /* This reason (u8) refers to enum qca_wlan_vendor_acs_select_reason. * This helps ACS module to understand why ACS needs to be started. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_REASON = 1, /* Flag attribute to indicate if driver supports spectral scanning */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_SPECTRAL_SUPPORTED = 2, /* Flag attribute to indicate if 11ac is offloaded to firmware */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_IS_OFFLOAD_ENABLED = 3, /* Flag attribute to indicate if driver provides additional channel * capability as part of scan operation */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_ADD_CHAN_STATS_SUPPORT = 4, /* Flag attribute to indicate interface status is UP */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_AP_UP = 5, /* Operating mode (u8) of interface. Takes one of enum nl80211_iftype * values. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_SAP_MODE = 6, /* Channel width (u8). It takes one of enum nl80211_chan_width values. * This is the upper bound of channel width. ACS logic should try to get * a channel with the specified width and if not found, look for lower * values. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_WIDTH = 7, /* This (u8) will hold values of one of enum nl80211_bands */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_BAND = 8, /* PHY/HW mode (u8). Takes one of enum qca_wlan_vendor_acs_hw_mode * values */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PHY_MODE = 9, /* Array of (u32) supported frequency list among which ACS should choose * best frequency. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_FREQ_LIST = 10, /* Preferred channel list by the driver which will have array of nested * values as per enum qca_wlan_vendor_attr_pcl attribute. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_PCL = 11, /* Array of nested attribute for each channel. It takes attr as defined * in enum qca_wlan_vendor_external_acs_event_chan_info_attr. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_CHAN_INFO = 12, /* External ACS policy such as PCL mandatory, PCL preferred, etc. * It uses values defined in enum * qca_wlan_vendor_attr_external_acs_policy. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_POLICY = 13, /* Reference RF Operating Parameter (RROP) availability information * (u16). It uses values defined in enum * qca_wlan_vendor_attr_rropavail_info. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_RROPAVAIL_INFO = 14, /* keep last */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_MAX = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_EVENT_LAST - 1, }; /** * enum qca_wlan_vendor_attr_external_acs_channels: Attributes to vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS. This carries a list of channels * in priority order as decided after ACS operation in userspace. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON: Required (u8). * One of reason code from enum qca_wlan_vendor_acs_select_reason. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST: Required * Array of nested values for each channel with following attributes: * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST is deprecated and use * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST * is still used if either of the driver or user space application doesn't * support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY: Required (u8). * Primary channel number * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY is deprecated and use * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY * is still used if either of the driver or user space application doesn't * support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY: Required (u8). * Secondary channel number, required only for 160 and 80+80 MHz bandwidths. * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY is deprecated and use * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY * is still used if either of the driver or user space application * doesn't support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0: Required (u8). * VHT seg0 channel number * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 is deprecated and use * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 * is still used if either of the driver or user space application * doesn't support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1: Required (u8). * VHT seg1 channel number * Note: If both the driver and user-space application supports the 6 GHz band, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 is deprecated and use * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1. * To maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 * is still used if either of the driver or user space application * doesn't support the 6 GHz band. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH: Required (u8). * Takes one of enum nl80211_chan_width values. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST: Required * Array of nested values for each channel with following attributes: * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY in MHz (u32), * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY in MHz (u32), * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0 in MHz (u32), * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1 in MHz (u32), * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH * Note: If user-space application has no support of the 6 GHz band, this * attribute is optional. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY: Required (u32) * Primary channel frequency in MHz * Note: If user-space application has no support of the 6 GHz band, this * attribute is optional. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY: Required (u32) * Secondary channel frequency in MHz used for HT 40 MHz channels. * Note: If user-space application has no support of the 6 GHz band, this * attribute is optional. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0: Required (u32) * VHT seg0 channel frequency in MHz * Note: If user-space application has no support of the 6GHz band, this * attribute is optional. * * @QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1: Required (u32) * VHT seg1 channel frequency in MHz * Note: If user-space application has no support of the 6 GHz band, this * attribute is optional. */ enum qca_wlan_vendor_attr_external_acs_channels { QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_INVALID = 0, /* One of reason code (u8) from enum qca_wlan_vendor_acs_select_reason */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_REASON = 1, /* Array of nested values for each channel with following attributes: * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1, * QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LIST = 2, /* This (u8) will hold values of one of enum nl80211_bands */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_BAND = 3, /* Primary channel (u8) */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_PRIMARY = 4, /* Secondary channel (u8) used for HT 40 MHz channels */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_SECONDARY = 5, /* VHT seg0 channel (u8) */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG0 = 6, /* VHT seg1 channel (u8) */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_CENTER_SEG1 = 7, /* Channel width (u8). Takes one of enum nl80211_chan_width values. */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_WIDTH = 8, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_LIST = 9, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_PRIMARY = 10, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_SECONDARY = 11, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG0 = 12, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_FREQUENCY_CENTER_SEG1 = 13, /* keep last */ QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST, QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_MAX = QCA_WLAN_VENDOR_ATTR_EXTERNAL_ACS_CHANNEL_LAST - 1 }; enum qca_chip_power_save_failure_reason { /* Indicates if the reason for the failure is due to a protocol * layer/module. */ QCA_CHIP_POWER_SAVE_FAILURE_REASON_PROTOCOL = 0, /* Indicates if the reason for the failure is due to a hardware issue. */ QCA_CHIP_POWER_SAVE_FAILURE_REASON_HARDWARE = 1, }; /** * qca_attr_chip_power_save_failure: Attributes to vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_CHIP_PWRSAVE_FAILURE. This carries the requisite * information leading to the power save failure. */ enum qca_attr_chip_power_save_failure { QCA_ATTR_CHIP_POWER_SAVE_FAILURE_INVALID = 0, /* Reason to cause the power save failure. * These reasons are represented by * enum qca_chip_power_save_failure_reason. */ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_REASON = 1, /* keep last */ QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST, QCA_ATTR_CHIP_POWER_SAVE_FAILURE_MAX = QCA_ATTR_CHIP_POWER_SAVE_FAILURE_LAST - 1, }; /** * qca_wlan_vendor_nud_stats_data_pkt_flags: Flag representing the various * data types for which the stats have to get collected. */ enum qca_wlan_vendor_nud_stats_data_pkt_flags { QCA_WLAN_VENDOR_NUD_STATS_DATA_ARP = 1 << 0, QCA_WLAN_VENDOR_NUD_STATS_DATA_DNS = 1 << 1, QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_HANDSHAKE = 1 << 2, QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV4 = 1 << 3, QCA_WLAN_VENDOR_NUD_STATS_DATA_ICMPV6 = 1 << 4, /* Used by QCA_ATTR_NUD_STATS_PKT_TYPE only in nud stats get * to represent the stats of respective data type. */ QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN = 1 << 5, QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_SYN_ACK = 1 << 6, QCA_WLAN_VENDOR_NUD_STATS_DATA_TCP_ACK = 1 << 7, }; enum qca_wlan_vendor_nud_stats_set_data_pkt_info { QCA_ATTR_NUD_STATS_DATA_PKT_INFO_INVALID = 0, /* Represents the data packet type to be monitored (u32). * Host driver tracks the stats corresponding to each data frame * represented by these flags. * These data packets are represented by * enum qca_wlan_vendor_nud_stats_data_pkt_flags */ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_TYPE = 1, /* Name corresponding to the DNS frame for which the respective DNS * stats have to get monitored (string). Max string length 255. */ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DNS_DOMAIN_NAME = 2, /* source port on which the respective proto stats have to get * collected (u32). */ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_SRC_PORT = 3, /* destination port on which the respective proto stats have to get * collected (u32). */ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_PORT = 4, /* IPv4 address for which the destined data packets have to be * monitored. (in network byte order), u32. */ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV4 = 5, /* IPv6 address for which the destined data packets have to be * monitored. (in network byte order), 16 bytes array. */ QCA_ATTR_NUD_STATS_DATA_PKT_INFO_DEST_IPV6 = 6, QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST, QCA_ATTR_NUD_STATS_DATA_PKT_INFO_MAX = QCA_ATTR_NUD_STATS_DATA_PKT_INFO_LAST - 1, }; /** * qca_wlan_vendor_attr_nud_stats_set: Attributes to vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_SET. This carries the requisite * information to start/stop the NUD statistics collection. */ enum qca_attr_nud_stats_set { QCA_ATTR_NUD_STATS_SET_INVALID = 0, /* Flag to start/stop the NUD statistics collection. * Start - If included, Stop - If not included */ QCA_ATTR_NUD_STATS_SET_START = 1, /* IPv4 address of the default gateway (in network byte order), u32 */ QCA_ATTR_NUD_STATS_GW_IPV4 = 2, /* Represents the list of data packet types to be monitored. * Host driver tracks the stats corresponding to each data frame * represented by these flags. * These data packets are represented by * enum qca_wlan_vendor_nud_stats_set_data_pkt_info */ QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO = 3, /* keep last */ QCA_ATTR_NUD_STATS_SET_LAST, QCA_ATTR_NUD_STATS_SET_MAX = QCA_ATTR_NUD_STATS_SET_LAST - 1, }; enum qca_attr_nud_data_stats { QCA_ATTR_NUD_DATA_STATS_INVALID = 0, /* Data packet type for which the stats are collected (u32). * Represented by enum qca_wlan_vendor_nud_stats_data_pkt_flags */ QCA_ATTR_NUD_STATS_PKT_TYPE = 1, /* Name corresponding to the DNS frame for which the respective DNS * stats are monitored (string). Max string length 255. */ QCA_ATTR_NUD_STATS_PKT_DNS_DOMAIN_NAME = 2, /* source port on which the respective proto stats are collected (u32). */ QCA_ATTR_NUD_STATS_PKT_SRC_PORT = 3, /* destination port on which the respective proto stats are collected * (u32). */ QCA_ATTR_NUD_STATS_PKT_DEST_PORT = 4, /* IPv4 address for which the destined data packets have to be * monitored. (in network byte order), u32. */ QCA_ATTR_NUD_STATS_PKT_DEST_IPV4 = 5, /* IPv6 address for which the destined data packets have to be * monitored. (in network byte order), 16 bytes array. */ QCA_ATTR_NUD_STATS_PKT_DEST_IPV6 = 6, /* Data packet Request count received from netdev (u32). */ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_FROM_NETDEV = 7, /* Data packet Request count sent to lower MAC from upper MAC (u32). */ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TO_LOWER_MAC = 8, /* Data packet Request count received by lower MAC from upper MAC * (u32) */ QCA_ATTR_NUD_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC = 9, /* Data packet Request count successfully transmitted by the device * (u32) */ QCA_ATTR_NUD_STATS_PKT_REQ_COUNT_TX_SUCCESS = 10, /* Data packet Response count received by lower MAC (u32) */ QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC = 11, /* Data packet Response count received by upper MAC (u32) */ QCA_ATTR_NUD_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC = 12, /* Data packet Response count delivered to netdev (u32) */ QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_TO_NETDEV = 13, /* Data Packet Response count that are dropped out of order (u32) */ QCA_ATTR_NUD_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP = 14, /* keep last */ QCA_ATTR_NUD_DATA_STATS_LAST, QCA_ATTR_NUD_DATA_STATS_MAX = QCA_ATTR_NUD_DATA_STATS_LAST - 1, }; /** * qca_attr_nud_stats_get: Attributes to vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_NUD_STATS_GET. This carries the requisite * NUD statistics collected when queried. */ enum qca_attr_nud_stats_get { QCA_ATTR_NUD_STATS_GET_INVALID = 0, /* ARP Request count from netdev (u32) */ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV = 1, /* ARP Request count sent to lower MAC from upper MAC (u32) */ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC = 2, /* ARP Request count received by lower MAC from upper MAC (u32) */ QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC = 3, /* ARP Request count successfully transmitted by the device (u32) */ QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS = 4, /* ARP Response count received by lower MAC (u32) */ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC = 5, /* ARP Response count received by upper MAC (u32) */ QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC = 6, /* ARP Response count delivered to netdev (u32) */ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV = 7, /* ARP Response count dropped due to out of order reception (u32) */ QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP = 8, /* Flag indicating if the station's link to the AP is active. * Active Link - If included, Inactive link - If not included */ QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE = 9, /* Flag indicating if there is any duplicate address detected (DAD). * Yes - If detected, No - If not detected. */ QCA_ATTR_NUD_STATS_IS_DAD = 10, /* List of Data packet types for which the stats are requested. * This list does not carry ARP stats as they are done by the * above attributes. Represented by enum qca_attr_nud_data_stats. */ QCA_ATTR_NUD_STATS_DATA_PKT_STATS = 11, /* keep last */ QCA_ATTR_NUD_STATS_GET_LAST, QCA_ATTR_NUD_STATS_GET_MAX = QCA_ATTR_NUD_STATS_GET_LAST - 1, }; enum qca_wlan_btm_candidate_status { QCA_STATUS_ACCEPT = 0, QCA_STATUS_REJECT_EXCESSIVE_FRAME_LOSS_EXPECTED = 1, QCA_STATUS_REJECT_EXCESSIVE_DELAY_EXPECTED = 2, QCA_STATUS_REJECT_INSUFFICIENT_QOS_CAPACITY = 3, QCA_STATUS_REJECT_LOW_RSSI = 4, QCA_STATUS_REJECT_HIGH_INTERFERENCE = 5, QCA_STATUS_REJECT_UNKNOWN = 6, }; enum qca_wlan_vendor_attr_btm_candidate_info { QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_INVALID = 0, /* 6-byte MAC address representing the BSSID of transition candidate */ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID = 1, /* Unsigned 32-bit value from enum qca_wlan_btm_candidate_status * returned by the driver. It says whether the BSSID provided in * QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_BSSID is acceptable by * the driver, if not it specifies the reason for rejection. * Note that the user-space can overwrite the transition reject reason * codes provided by driver based on more information. */ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_STATUS = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_MAX = QCA_WLAN_VENDOR_ATTR_BTM_CANDIDATE_INFO_AFTER_LAST - 1, }; enum qca_attr_trace_level { QCA_ATTR_TRACE_LEVEL_INVALID = 0, /* * Nested array of the following attributes: * QCA_ATTR_TRACE_LEVEL_MODULE, * QCA_ATTR_TRACE_LEVEL_MASK. */ QCA_ATTR_TRACE_LEVEL_PARAM = 1, /* * Specific QCA host driver module. Please refer to the QCA host * driver implementation to get the specific module ID. */ QCA_ATTR_TRACE_LEVEL_MODULE = 2, /* Different trace level masks represented in the QCA host driver. */ QCA_ATTR_TRACE_LEVEL_MASK = 3, /* keep last */ QCA_ATTR_TRACE_LEVEL_AFTER_LAST, QCA_ATTR_TRACE_LEVEL_MAX = QCA_ATTR_TRACE_LEVEL_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_get_he_capabilities - IEEE 802.11ax HE capabilities */ enum qca_wlan_vendor_attr_get_he_capabilities { QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_INVALID = 0, /* Whether HE capabilities is supported * (u8 attribute: 0 = not supported, 1 = supported) */ QCA_WLAN_VENDOR_ATTR_HE_SUPPORTED = 1, /* HE PHY capabilities, array of 3 u32 values */ QCA_WLAN_VENDOR_ATTR_PHY_CAPAB = 2, /* HE MAC capabilities (u32 attribute) */ QCA_WLAN_VENDOR_ATTR_MAC_CAPAB = 3, /* HE MCS map (u32 attribute) */ QCA_WLAN_VENDOR_ATTR_HE_MCS = 4, /* Number of SS (u32 attribute) */ QCA_WLAN_VENDOR_ATTR_NUM_SS = 5, /* RU count (u32 attribute) */ QCA_WLAN_VENDOR_ATTR_RU_IDX_MASK = 6, /* PPE threshold data, array of 8 u32 values */ QCA_WLAN_VENDOR_ATTR_PPE_THRESHOLD = 7, /* keep last */ QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_MAX = QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_spectral_scan - Spectral scan config parameters */ enum qca_wlan_vendor_attr_spectral_scan { QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INVALID = 0, /* Number of times the chip enters spectral scan mode before * deactivating spectral scans. When set to 0, chip will enter spectral * scan mode continuously. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT = 1, /* Spectral scan period. Period increment resolution is 256*Tclk, * where Tclk = 1/44 MHz (Gmode), 1/40 MHz (Amode). u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD = 2, /* Spectral scan priority. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY = 3, /* Number of FFT data points to compute. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE = 4, /* Enable targeted gain change before starting the spectral scan FFT. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA = 5, /* Restart a queued spectral scan. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA = 6, /* Noise floor reference number for the calculation of bin power. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF = 7, /* Disallow spectral scan triggers after TX/RX packets by setting * this delay value to roughly SIFS time period or greater. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY = 8, /* Number of strong bins (inclusive) per sub-channel, below * which a signal is declared a narrow band tone. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR = 9, /* Specify the threshold over which a bin is declared strong (for * scan bandwidth analysis). u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR = 10, /* Spectral scan report mode. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE = 11, /* RSSI report mode, if the ADC RSSI is below * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR, * then FFTs will not trigger, but timestamps and summaries get * reported. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE = 12, /* ADC RSSI must be greater than or equal to this threshold (signed dB) * to ensure spectral scan reporting with normal error code. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR = 13, /* Format of frequency bin magnitude for spectral scan triggered FFTs: * 0: linear magnitude, 1: log magnitude (20*log10(lin_mag)). * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT = 14, /* Format of FFT report to software for spectral scan triggered FFTs. * 0: No FFT report (only spectral scan summary report) * 1: 2-dword summary of metrics for each completed FFT + spectral scan * report * 2: 2-dword summary of metrics for each completed FFT + 1x-oversampled * bins (in-band) per FFT + spectral scan summary report * 3: 2-dword summary of metrics for each completed FFT + 2x-oversampled * bins (all) per FFT + spectral scan summary report * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE = 15, /* Number of LSBs to shift out in order to scale the FFT bins. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE = 16, /* Set to 1 (with spectral_scan_pwr_format=1), to report bin magnitudes * in dBm power. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ = 17, /* Per chain enable mask to select input ADC for search FFT. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK = 18, /* An unsigned 64-bit integer provided by host driver to identify the * spectral scan request. This attribute is included in the scan * response message for @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START * and used as an attribute in * @QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_STOP to identify the * specific scan to be stopped. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE = 19, /* Skip interval for FFT reports. u32 attribute */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD = 20, /* Set to report only one set of FFT results. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT = 21, /* Debug level for spectral module in driver. * 0 : Verbosity level 0 * 1 : Verbosity level 1 * 2 : Verbosity level 2 * 3 : Matched filterID display * 4 : One time dump of FFT report * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL = 22, /* Type of spectral scan request. u32 attribute. * It uses values defined in enum * qca_wlan_vendor_attr_spectral_scan_request_type. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE = 23, /* This specifies the frequency span over which spectral * scan would be carried out. Its value depends on the * value of QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE and * the relation is as follows. * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL * Not applicable. Spectral scan would happen in the * operating span. * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE * Center frequency (in MHz) of the span of interest or * for convenience, center frequency (in MHz) of any channel * in the span of interest. For 80+80 MHz agile spectral scan * request it represents center frequency (in MHz) of the primary * 80 MHz span or for convenience, center frequency (in MHz) of any * channel in the primary 80 MHz span. If agile spectral scan is * initiated without setting a valid frequency it returns the * error code * (QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED). * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY = 24, /* Spectral scan mode. u32 attribute. * It uses values defined in enum qca_wlan_vendor_spectral_scan_mode. * If this attribute is not present, it is assumed to be * normal mode (QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL). */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE = 25, /* Spectral scan error code. u32 attribute. * It uses values defined in enum * qca_wlan_vendor_spectral_scan_error_code. * This attribute is included only in failure scenarios. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE = 26, /* 8-bit unsigned value to enable/disable debug of the * Spectral DMA ring. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG = 27, /* 8-bit unsigned value to enable/disable debug of the * Spectral DMA buffers. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG = 28, /* This specifies the frequency span over which spectral scan would be * carried out. Its value depends on the value of * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE and the relation is as * follows. * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL * Not applicable. Spectral scan would happen in the operating span. * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE * This attribute is applicable only for agile spectral scan * requests in 80+80 MHz mode. It represents center frequency (in * MHz) of the secondary 80 MHz span or for convenience, center * frequency (in MHz) of any channel in the secondary 80 MHz span. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29, /* This attribute specifies the bandwidth to be used for spectral scan * operation. This is an u8 attribute and uses the values in enum * nl80211_chan_width. This is an optional attribute. * If this attribute is not populated, the driver should configure the * spectral scan bandwidth to the maximum value supported by the target * for the current operating bandwidth. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH = 30, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_spectral_diag_stats - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_DIAG_STATS. */ enum qca_wlan_vendor_attr_spectral_diag_stats { QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_INVALID = 0, /* Number of spectral TLV signature mismatches. * u64 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH = 1, /* Number of spectral phyerror events with insufficient length when * parsing for secondary 80 search FFT report. u64 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN = 2, /* Number of spectral phyerror events without secondary 80 * search FFT report. u64 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT = 3, /* Number of spectral phyerror events with vht operation segment 1 id * mismatches in search fft report. u64 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH = 4, /* Number of spectral phyerror events with vht operation segment 2 id * mismatches in search fft report. u64 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH = 5, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX = QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_spectral_cap - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. */ enum qca_wlan_vendor_attr_spectral_cap { QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_INVALID = 0, /* Flag attribute to indicate phydiag capability */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG = 1, /* Flag attribute to indicate radar detection capability */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR = 2, /* Flag attribute to indicate spectral capability */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL = 3, /* Flag attribute to indicate advanced spectral capability */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL = 4, /* Spectral hardware generation. u32 attribute. * It uses values defined in enum * qca_wlan_vendor_spectral_scan_cap_hw_gen. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN = 5, /* Spectral bin scaling formula ID. u16 attribute. * It uses values defined in enum * qca_wlan_vendor_spectral_scan_cap_formula_id. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID = 6, /* Spectral bin scaling param - low level offset. * s16 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_LOW_LEVEL_OFFSET = 7, /* Spectral bin scaling param - high level offset. * s16 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HIGH_LEVEL_OFFSET = 8, /* Spectral bin scaling param - RSSI threshold. * s16 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RSSI_THR = 9, /* Spectral bin scaling param - default AGC max gain. * u8 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN = 10, /* Flag attribute to indicate agile spectral scan capability * for 20/40/80 MHz modes. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL = 11, /* Flag attribute to indicate agile spectral scan capability * for 160 MHz mode. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_160 = 12, /* Flag attribute to indicate agile spectral scan capability * for 80+80 MHz mode. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80 = 13, /* Number of spectral detectors used for scan in 20 MHz. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_20_MHZ = 14, /* Number of spectral detectors used for scan in 40 MHz. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_40_MHZ = 15, /* Number of spectral detectors used for scan in 80 MHz. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80_MHZ = 16, /* Number of spectral detectors used for scan in 160 MHz. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_160_MHZ = 17, /* Number of spectral detectors used for scan in 80+80 MHz. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18, /* Flag attribute to indicate agile spectral scan capability * for 320 MHz mode. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320 = 19, /* Number of spectral detectors used for scan in 320 MHz. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ = 20, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX = QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_spectral_scan_status - used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS. */ enum qca_wlan_vendor_attr_spectral_scan_status { QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_INVALID = 0, /* Flag attribute to indicate whether spectral scan is enabled */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED = 1, /* Flag attribute to indicate whether spectral scan is in progress*/ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE = 2, /* Spectral scan mode. u32 attribute. * It uses values defined in enum qca_wlan_vendor_spectral_scan_mode. * If this attribute is not present, normal mode * (QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL is assumed to be * requested. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE = 3, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX = QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_AFTER_LAST - 1, }; /** * qca_wlan_vendor_attr_spectral_scan_request_type: Attribute values for * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE to the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START. This represents the * spectral scan request types. * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG: Request to * set the spectral parameters and start scan. * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN: Request to * only set the spectral parameters. * @QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG: Request to * only start the spectral scan. */ enum qca_wlan_vendor_attr_spectral_scan_request_type { QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN_AND_CONFIG, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_SCAN, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE_CONFIG, }; /** * qca_wlan_vendor_spectral_scan_mode: Attribute values for * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE in the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START and * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE in the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS. This represents the * spectral scan modes. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL: Normal spectral scan: * spectral scan in the current operating span. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE: Agile spectral scan: * spectral scan in the configured agile span. */ enum qca_wlan_vendor_spectral_scan_mode { QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL = 0, QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE = 1, }; /** * qca_wlan_vendor_spectral_scan_error_code: Attribute values for * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE in the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_START. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED: Changing the value * of a parameter is not supported. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED: Requested spectral scan * mode is not supported. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE: A parameter * has invalid value. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED: A parameter * is not initialized. */ enum qca_wlan_vendor_spectral_scan_error_code { QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED = 0, QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED = 1, QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE = 2, QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED = 3, }; /** * qca_wlan_vendor_spectral_scan_cap_hw_gen: Attribute values for * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN to the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the * spectral hardware generation. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1: generation 1 * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2: generation 2 * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3: generation 3 */ enum qca_wlan_vendor_spectral_scan_cap_hw_gen { QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_1 = 0, QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_2 = 1, QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_HW_GEN_3 = 2, }; enum qca_wlan_vendor_tos { QCA_WLAN_VENDOR_TOS_BK = 0, QCA_WLAN_VENDOR_TOS_BE = 1, QCA_WLAN_VENDOR_TOS_VI = 2, QCA_WLAN_VENDOR_TOS_VO = 3, }; /** * enum qca_wlan_vendor_attr_active_tos - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_ACTIVE_TOS. */ enum qca_wlan_vendor_attr_active_tos { QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_INVALID = 0, /* Type Of Service - Represented by qca_wlan_vendor_tos */ QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS = 1, /* Flag attribute representing the start (attribute included) or stop * (attribute not included) of the respective TOS. */ QCA_WLAN_VENDOR_ATTR_ACTIVE_TOS_START = 2, }; enum qca_wlan_vendor_hang_reason { /* Unspecified reason */ QCA_WLAN_HANG_REASON_UNSPECIFIED = 0, /* No Map for the MAC entry for the received frame */ QCA_WLAN_HANG_RX_HASH_NO_ENTRY_FOUND = 1, /* Peer deletion timeout happened */ QCA_WLAN_HANG_PEER_DELETION_TIMEDOUT = 2, /* Peer unmap timeout */ QCA_WLAN_HANG_PEER_UNMAP_TIMEDOUT = 3, /* Scan request timed out */ QCA_WLAN_HANG_SCAN_REQ_EXPIRED = 4, /* Consecutive Scan attempt failures */ QCA_WLAN_HANG_SCAN_ATTEMPT_FAILURES = 5, /* Unable to get the message buffer */ QCA_WLAN_HANG_GET_MSG_BUFF_FAILURE = 6, /* Current command processing is timedout */ QCA_WLAN_HANG_ACTIVE_LIST_TIMEOUT = 7, /* Timeout for an ACK from FW for suspend request */ QCA_WLAN_HANG_SUSPEND_TIMEOUT = 8, /* Timeout for an ACK from FW for resume request */ QCA_WLAN_HANG_RESUME_TIMEOUT = 9, /* Transmission timeout for consecutive data frames */ QCA_WLAN_HANG_TRANSMISSIONS_TIMEOUT = 10, /* Timeout for the TX completion status of data frame */ QCA_WLAN_HANG_TX_COMPLETE_TIMEOUT = 11, /* DXE failure for TX/RX, DXE resource unavailability */ QCA_WLAN_HANG_DXE_FAILURE = 12, /* WMI pending commands exceed the maximum count */ QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13, /* Timeout for peer STA connection accept command's response from the * FW in AP mode. This command is triggered when a STA (peer) connects * to AP (DUT). */ QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT = 14, /* Timeout for the AP connection accept command's response from the FW * in STA mode. This command is triggered when the STA (DUT) connects * to an AP (peer). */ QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT = 15, /* Timeout waiting for the response to the MAC HW mode change command * sent to FW as a part of MAC mode switch among DBS (Dual Band * Simultaneous), SCC (Single Channel Concurrency), and MCC (Multi * Channel Concurrency) mode. */ QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT = 16, /* Timeout waiting for the response from FW to configure the MAC HW's * mode. This operation is to configure the single/two MACs in either * SCC/MCC/DBS mode. */ QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT = 17, /* Timeout waiting for response of VDEV start command from the FW */ QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT = 18, /* Timeout waiting for response of VDEV restart command from the FW */ QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT = 19, /* Timeout waiting for response of VDEV stop command from the FW */ QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT = 20, /* Timeout waiting for response of VDEV delete command from the FW */ QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT = 21, /* Timeout waiting for response of peer all delete request command to * the FW on a specific VDEV. */ QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22, /* WMI sequence mismatch between WMI command and Tx completion */ QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23, /* Write to Device HAL register failed */ QCA_WLAN_HANG_REG_WRITE_FAILURE = 24, /* No credit left to send the wow_wakeup_from_sleep to firmware */ QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25, /* Bus failure */ QCA_WLAN_HANG_BUS_FAILURE = 26, /* tasklet/credit latency found */ QCA_WLAN_HANG_TASKLET_CREDIT_LATENCY_DETECT = 27, }; /** * enum qca_wlan_vendor_attr_hang - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_HANG. */ enum qca_wlan_vendor_attr_hang { QCA_WLAN_VENDOR_ATTR_HANG_INVALID = 0, /* Reason for the hang - u32 attribute with a value from enum * qca_wlan_vendor_hang_reason. */ QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1, /* The binary blob data associated with the hang reason specified by * QCA_WLAN_VENDOR_ATTR_HANG_REASON. This binary data is expected to * contain the required dump to analyze the reason for the hang. * NLA_BINARY attribute, the max size is 1024 bytes. */ QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA = 2, QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HANG_MAX = QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_flush_pending - Attributes for * flushing pending traffic in firmware. * * @QCA_WLAN_VENDOR_ATTR_PEER_ADDR: Configure peer MAC address. * @QCA_WLAN_VENDOR_ATTR_AC: Configure access category of the pending * packets. It is u8 value with bit 0~3 represent AC_BE, AC_BK, * AC_VI, AC_VO respectively. Set the corresponding bit to 1 to * flush packets with access category. */ enum qca_wlan_vendor_attr_flush_pending { QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_INVALID = 0, QCA_WLAN_VENDOR_ATTR_PEER_ADDR = 1, QCA_WLAN_VENDOR_ATTR_AC = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_MAX = QCA_WLAN_VENDOR_ATTR_FLUSH_PENDING_AFTER_LAST - 1, }; /** * qca_wlan_vendor_spectral_scan_cap_formula_id: Attribute values for * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID in the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_CAP_INFO. This represents the * Spectral bin scaling formula ID. * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_NO_SCALING: No scaling * @QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_AGC_GAIN_RSSI_CORR_BASED: AGC gain * and RSSI threshold based formula. */ enum qca_wlan_vendor_spectral_scan_cap_formula_id { QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_NO_SCALING = 0, QCA_WLAN_VENDOR_SPECTRAL_SCAN_CAP_AGC_GAIN_RSSI_CORR_BASED = 1, }; /** * enum qca_wlan_vendor_attr_rropavail_info - Specifies whether Representative * RF Operating Parameter (RROP) information is available, and if so, at which * point in the application-driver interaction sequence it can be retrieved by * the application from the driver. This point may vary by architecture and * other factors. This is a u16 value. */ enum qca_wlan_vendor_attr_rropavail_info { /* RROP information is unavailable. */ QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_UNAVAILABLE, /* RROP information is available and the application can retrieve the * information after receiving an QCA_NL80211_VENDOR_SUBCMD_EXTERNAL_ACS * event from the driver. */ QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_EXTERNAL_ACS_START, /* RROP information is available only after a vendor specific scan * (requested using QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN) has * successfully completed. The application can retrieve the information * after receiving the QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE event from * the driver. */ QCA_WLAN_VENDOR_ATTR_RROPAVAIL_INFO_VSCAN_END, }; /** * enum qca_wlan_vendor_attr_rrop_info - Specifies vendor specific * Representative RF Operating Parameter (RROP) information. It is sent for the * vendor command QCA_NL80211_VENDOR_SUBCMD_GET_RROP_INFO. This information is * intended for use by external Auto Channel Selection applications. It provides * guidance values for some RF parameters that are used by the system during * operation. These values could vary by channel, band, radio, and so on. */ enum qca_wlan_vendor_attr_rrop_info { QCA_WLAN_VENDOR_ATTR_RROP_INFO_INVALID = 0, /* Representative Tx Power List (RTPL) which has an array of nested * values as per attributes in enum qca_wlan_vendor_attr_rtplinst. */ QCA_WLAN_VENDOR_ATTR_RROP_INFO_RTPL = 1, QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_RROP_INFO_MAX = QCA_WLAN_VENDOR_ATTR_RROP_INFO_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_rtplinst - Specifies attributes for individual list * entry instances in the Representative Tx Power List (RTPL). It provides * simplified power values intended for helping external Auto channel Selection * applications compare potential Tx power performance between channels, other * operating conditions remaining identical. These values are not necessarily * the actual Tx power values that will be used by the system. They are also not * necessarily the max or average values that will be used. Instead, they are * relative, summarized keys for algorithmic use computed by the driver or * underlying firmware considering a number of vendor specific factors. */ enum qca_wlan_vendor_attr_rtplinst { QCA_WLAN_VENDOR_ATTR_RTPLINST_INVALID = 0, /* Primary channel number (u8). * Note: If both the driver and user space application support the * 6 GHz band, this attribute is deprecated and * QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY_FREQUENCY should be used. To * maintain backward compatibility, * QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY is still used if either the * driver or user space application or both do not support the 6 GHz * band. */ QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY = 1, /* Representative Tx power in dBm (s32) with emphasis on throughput. */ QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_THROUGHPUT = 2, /* Representative Tx power in dBm (s32) with emphasis on range. */ QCA_WLAN_VENDOR_ATTR_RTPLINST_TXPOWER_RANGE = 3, /* Primary channel center frequency (u32) in MHz */ QCA_WLAN_VENDOR_ATTR_RTPLINST_PRIMARY_FREQUENCY = 4, QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_RTPLINST_MAX = QCA_WLAN_VENDOR_ATTR_RTPLINST_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_config_latency_level - Level for * wlan latency module. * * There will be various of Wi-Fi functionality like scan/roaming/adaptive * power saving which would causing data exchange out of service, this * would be a big impact on latency. For latency sensitive applications over * Wi-Fi are intolerant to such operations and thus would configure them * to meet their respective needs. It is well understood by such applications * that altering the default behavior would degrade the Wi-Fi functionality * w.r.t the above pointed WLAN operations. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL: * Default WLAN operation level which throughput orientated. * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE: * Use moderate level to improve latency by limit scan duration. * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW: * Use low latency level to benifit application like concurrent * downloading or video streaming via constraint scan/adaptive PS. * @QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW: * Use ultra low latency level to benefit for gaming/voice * application via constraint scan/roaming/adaptive PS. */ enum qca_wlan_vendor_attr_config_latency_level { QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_INVALID = 0, QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_NORMAL = 1, QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MODERATE = 2, QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_LOW = 3, QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_ULTRALOW = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_MAX = QCA_WLAN_VENDOR_ATTR_CONFIG_LATENCY_LEVEL_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_wlan_mac - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO. */ enum qca_wlan_vendor_attr_mac { QCA_WLAN_VENDOR_ATTR_MAC_INVALID = 0, /* MAC mode info list which has an array of nested values as * per attributes in enum qca_wlan_vendor_attr_mac_mode_info. */ QCA_WLAN_VENDOR_ATTR_MAC_INFO = 1, /* keep last */ QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAC_MAX = QCA_WLAN_VENDOR_ATTR_MAC_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_mac_iface_info - Information of the connected * Wi-Fi netdev interface on a respective MAC. * Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO. */ enum qca_wlan_vendor_attr_mac_iface_info { QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_INVALID = 0, /* Wi-Fi netdev's interface index (u32) */ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_IFINDEX = 1, /* Associated frequency in MHz of the connected Wi-Fi interface (u32) */ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_FREQ = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_MAX = QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_mac_info - Points to MAC the information. * Used by the attribute QCA_WLAN_VENDOR_ATTR_MAC_INFO of the * vendor command QCA_NL80211_VENDOR_SUBCMD_WLAN_MAC_INFO. */ enum qca_wlan_vendor_attr_mac_info { QCA_WLAN_VENDOR_ATTR_MAC_INFO_INVALID = 0, /* Hardware MAC ID associated for the MAC (u32) */ QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAC_ID = 1, /* Band supported by the MAC at a given point. * This is a u32 bitmask of BIT(NL80211_BAND_*) as described in %enum * nl80211_band. */ QCA_WLAN_VENDOR_ATTR_MAC_INFO_BAND = 2, /* Refers to list of WLAN netdev interfaces associated with this MAC. * Represented by enum qca_wlan_vendor_attr_mac_iface_info. */ QCA_WLAN_VENDOR_ATTR_MAC_IFACE_INFO = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAC_INFO_MAX = QCA_WLAN_VENDOR_ATTR_MAC_INFO_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_get_logger_features - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET. */ enum qca_wlan_vendor_attr_get_logger_features { QCA_WLAN_VENDOR_ATTR_LOGGER_INVALID = 0, /* Unsigned 32-bit enum value of wifi_logger_supported_features */ QCA_WLAN_VENDOR_ATTR_LOGGER_SUPPORTED = 1, /* keep last */ QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LOGGER_MAX = QCA_WLAN_VENDOR_ATTR_LOGGER_AFTER_LAST - 1, }; /** * enum wifi_logger_supported_features - Values for supported logger features */ enum wifi_logger_supported_features { WIFI_LOGGER_MEMORY_DUMP_FEATURE = (1 << (0)), WIFI_LOGGER_PER_PACKET_TX_RX_STATUS_FEATURE = (1 << (1)), WIFI_LOGGER_CONNECT_EVENT_FEATURE = (1 << (2)), WIFI_LOGGER_POWER_EVENT_FEATURE = (1 << (3)), WIFI_LOGGER_WAKE_LOCK_FEATURE = (1 << (4)), WIFI_LOGGER_VERBOSE_FEATURE = (1 << (5)), WIFI_LOGGER_WATCHDOG_TIMER_FEATURE = (1 << (6)), WIFI_LOGGER_DRIVER_DUMP_FEATURE = (1 << (7)), WIFI_LOGGER_PACKET_FATE_FEATURE = (1 << (8)), }; /** * enum qca_wlan_tdls_caps_features_supported - Values for TDLS get * capabilities features */ enum qca_wlan_tdls_caps_features_supported { WIFI_TDLS_SUPPORT = (1 << (0)), WIFI_TDLS_EXTERNAL_CONTROL_SUPPORT = (1 << (1)), WIFI_TDLS_OFFCHANNEL_SUPPORT = (1 << (2)) }; /** * enum qca_wlan_vendor_attr_tdls_get_capabilities - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_TDLS_GET_CAPABILITIES. */ enum qca_wlan_vendor_attr_tdls_get_capabilities { QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_INVALID = 0, /* Indicates the max concurrent sessions */ /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX_CONC_SESSIONS, /* Indicates the support for features */ /* Unsigned 32-bit bitmap qca_wlan_tdls_caps_features_supported */ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_FEATURES_SUPPORTED, /* keep last */ QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_MAX = QCA_WLAN_VENDOR_ATTR_TDLS_GET_CAPS_AFTER_LAST - 1, }; /** * enum qca_wlan_offloaded_packets_sending_control - Offload packets control * command used as value for the attribute * QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL. */ enum qca_wlan_offloaded_packets_sending_control { QCA_WLAN_OFFLOADED_PACKETS_SENDING_CONTROL_INVALID = 0, QCA_WLAN_OFFLOADED_PACKETS_SENDING_START, QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP }; /** * enum qca_wlan_vendor_attr_offloaded_packets - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS. */ enum qca_wlan_vendor_attr_offloaded_packets { QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_INVALID = 0, /* Takes valid value from the enum * qca_wlan_offloaded_packets_sending_control * Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID, /* array of u8 len: Max packet size */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET_DATA, /* 6-byte MAC address used to represent source MAC address */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR, /* 6-byte MAC address used to represent destination MAC address */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR, /* Unsigned 32-bit value, in milli seconds */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD, /* This optional unsigned 16-bit attribute is used for specifying * ethernet protocol type. If not specified ethertype defaults to IPv4. */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_ETHER_PROTO_TYPE, /* keep last */ QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_MAX = QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_AFTER_LAST - 1, }; /** * enum qca_wlan_rssi_monitoring_control - RSSI control commands used as values * by the attribute QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL. */ enum qca_wlan_rssi_monitoring_control { QCA_WLAN_RSSI_MONITORING_CONTROL_INVALID = 0, QCA_WLAN_RSSI_MONITORING_START, QCA_WLAN_RSSI_MONITORING_STOP, }; /** * enum qca_wlan_vendor_attr_rssi_monitoring - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI. */ enum qca_wlan_vendor_attr_rssi_monitoring { QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_INVALID = 0, /* Takes valid value from the enum * qca_wlan_rssi_monitoring_control * Unsigned 32-bit value enum qca_wlan_rssi_monitoring_control */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID, /* Signed 8-bit value in dBm */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI, /* Signed 8-bit value in dBm */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI, /* attributes to be used/received in callback */ /* 6-byte MAC address used to represent current BSSID MAC address */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID, /* Signed 8-bit value indicating the current RSSI */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI, /* keep last */ QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX = QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_ndp_params - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_NDP. */ enum qca_wlan_vendor_attr_ndp_params { QCA_WLAN_VENDOR_ATTR_NDP_PARAM_INVALID = 0, /* Unsigned 32-bit value * enum of sub commands values in qca_wlan_ndp_sub_cmd */ QCA_WLAN_VENDOR_ATTR_NDP_SUBCMD, /* Unsigned 16-bit value */ QCA_WLAN_VENDOR_ATTR_NDP_TRANSACTION_ID, /* NL attributes for data used NDP SUB cmds */ /* Unsigned 32-bit value indicating a service info */ QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_INSTANCE_ID, /* Unsigned 32-bit value; channel frequency in MHz */ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL, /* Interface Discovery MAC address. An array of 6 Unsigned int8 */ QCA_WLAN_VENDOR_ATTR_NDP_PEER_DISCOVERY_MAC_ADDR, /* Interface name on which NDP is being created */ QCA_WLAN_VENDOR_ATTR_NDP_IFACE_STR, /* Unsigned 32-bit value for security */ /* CONFIG_SECURITY is deprecated, use NCS_SK_TYPE/PMK/SCID instead */ QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_SECURITY, /* Unsigned 32-bit value for QoS */ QCA_WLAN_VENDOR_ATTR_NDP_CONFIG_QOS, /* Array of u8: len = QCA_WLAN_VENDOR_ATTR_NAN_DP_APP_INFO_LEN */ QCA_WLAN_VENDOR_ATTR_NDP_APP_INFO, /* Unsigned 32-bit value for NDP instance Id */ QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID, /* Array of instance Ids */ QCA_WLAN_VENDOR_ATTR_NDP_INSTANCE_ID_ARRAY, /* Unsigned 32-bit value for initiator/responder NDP response code * accept/reject */ QCA_WLAN_VENDOR_ATTR_NDP_RESPONSE_CODE, /* NDI MAC address. An array of 6 Unsigned int8 */ QCA_WLAN_VENDOR_ATTR_NDP_NDI_MAC_ADDR, /* Unsigned 32-bit value errors types returned by driver * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy * NanStatusType includes these values. */ QCA_WLAN_VENDOR_ATTR_NDP_DRV_RESPONSE_STATUS_TYPE, /* Unsigned 32-bit value error values returned by driver * The nan_i.h in AOSP project platform/hardware/qcom/wlan * NanInternalStatusType includes these values. */ QCA_WLAN_VENDOR_ATTR_NDP_DRV_RETURN_VALUE, /* Unsigned 32-bit value for Channel setup configuration * The wifi_nan.h in AOSP project platform/hardware/libhardware_legacy * NanDataPathChannelCfg includes these values. */ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_CONFIG, /* Unsigned 32-bit value for Cipher Suite Shared Key Type */ QCA_WLAN_VENDOR_ATTR_NDP_CSID, /* Array of u8: len = NAN_PMK_INFO_LEN 32 bytes */ QCA_WLAN_VENDOR_ATTR_NDP_PMK, /* Security Context Identifier that contains the PMKID * Array of u8: len = NAN_SCID_BUF_LEN 1024 bytes */ QCA_WLAN_VENDOR_ATTR_NDP_SCID, /* Array of u8: len = NAN_SECURITY_MAX_PASSPHRASE_LEN 63 bytes */ QCA_WLAN_VENDOR_ATTR_NDP_PASSPHRASE, /* Array of u8: len = NAN_MAX_SERVICE_NAME_LEN 255 bytes */ QCA_WLAN_VENDOR_ATTR_NDP_SERVICE_NAME, /* Unsigned 32-bit bitmap indicating schedule update * BIT_0: NSS Update * BIT_1: Channel list update */ QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_REASON, /* Unsigned 32-bit value for NSS */ QCA_WLAN_VENDOR_ATTR_NDP_NSS, /* Unsigned 32-bit value for NUMBER NDP CHANNEL */ QCA_WLAN_VENDOR_ATTR_NDP_NUM_CHANNELS, /* Unsigned 32-bit value for CHANNEL BANDWIDTH * 0:20 MHz, 1:40 MHz, 2:80 MHz, 3:160 MHz */ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_WIDTH, /* Array of channel/band width */ QCA_WLAN_VENDOR_ATTR_NDP_CHANNEL_INFO, /* IPv6 address used by NDP (in network byte order), 16 bytes array. * This attribute is used and optional for ndp request, ndp response, * ndp indication, and ndp confirm. */ QCA_WLAN_VENDOR_ATTR_NDP_IPV6_ADDR = 27, /* Unsigned 16-bit value indicating transport port used by NDP. * This attribute is used and optional for ndp response, ndp indication, * and ndp confirm. */ QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PORT = 28, /* Unsigned 8-bit value indicating protocol used by NDP and assigned by * the Internet Assigned Numbers Authority (IANA) as per: * https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml * This attribute is used and optional for ndp response, ndp indication, * and ndp confirm. */ QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PROTOCOL = 29, /* Unsigned 8-bit value indicating if NDP remote peer supports NAN NDPE. * 1:support 0:not support */ QCA_WLAN_VENDOR_ATTR_PEER_NDPE_SUPPORT = 30, /* keep last */ QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_MAX = QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST - 1, }; enum qca_wlan_ndp_sub_cmd { QCA_WLAN_VENDOR_ATTR_NDP_INVALID = 0, /* Command to create a NAN data path interface */ QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_CREATE = 1, /* Command to delete a NAN data path interface */ QCA_WLAN_VENDOR_ATTR_NDP_INTERFACE_DELETE = 2, /* Command to initiate a NAN data path session */ QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_REQUEST = 3, /* Command to notify if the NAN data path session was sent */ QCA_WLAN_VENDOR_ATTR_NDP_INITIATOR_RESPONSE = 4, /* Command to respond to NAN data path session */ QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_REQUEST = 5, /* Command to notify on the responder about the response */ QCA_WLAN_VENDOR_ATTR_NDP_RESPONDER_RESPONSE = 6, /* Command to initiate a NAN data path end */ QCA_WLAN_VENDOR_ATTR_NDP_END_REQUEST = 7, /* Command to notify the if end request was sent */ QCA_WLAN_VENDOR_ATTR_NDP_END_RESPONSE = 8, /* Command to notify the peer about the end request */ QCA_WLAN_VENDOR_ATTR_NDP_REQUEST_IND = 9, /* Command to confirm the NAN data path session is complete */ QCA_WLAN_VENDOR_ATTR_NDP_CONFIRM_IND = 10, /* Command to indicate the peer about the end request being received */ QCA_WLAN_VENDOR_ATTR_NDP_END_IND = 11, /* Command to indicate the peer of schedule update */ QCA_WLAN_VENDOR_ATTR_NDP_SCHEDULE_UPDATE_IND = 12 }; /** * enum qca_wlan_vendor_attr_nd_offload - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD. */ enum qca_wlan_vendor_attr_nd_offload { QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_INVALID = 0, /* Flag to set Neighbour Discovery offload */ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, /* Keep last */ QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_MAX = QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_AFTER_LAST - 1, }; /** * enum packet_filter_sub_cmd - Packet filter sub commands */ enum packet_filter_sub_cmd { /** * Write packet filter program and/or data. The driver/firmware should * disable APF before writing into local buffer and re-enable APF after * writing is done. */ QCA_WLAN_SET_PACKET_FILTER = 1, /* Get packet filter feature capabilities from driver */ QCA_WLAN_GET_PACKET_FILTER = 2, /** * Write packet filter program and/or data. User space will send the * %QCA_WLAN_DISABLE_PACKET_FILTER command before issuing this command * and will send the %QCA_WLAN_ENABLE_PACKET_FILTER afterwards. The key * difference from that %QCA_WLAN_SET_PACKET_FILTER is the control over * enable/disable is given to user space with this command. Also, * user space sends the length of program portion in the buffer within * %QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH. */ QCA_WLAN_WRITE_PACKET_FILTER = 3, /* Read packet filter program and/or data */ QCA_WLAN_READ_PACKET_FILTER = 4, /* Enable APF feature */ QCA_WLAN_ENABLE_PACKET_FILTER = 5, /* Disable APF feature */ QCA_WLAN_DISABLE_PACKET_FILTER = 6, }; /** * enum qca_wlan_vendor_attr_packet_filter - BPF control commands used by * vendor QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER. */ enum qca_wlan_vendor_attr_packet_filter { QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID = 0, /* Unsigned 32-bit enum passed using packet_filter_sub_cmd */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD, /* Unsigned 32-bit value indicating the packet filter version */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION, /* Unsigned 32-bit value indicating the packet filter id */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID, /** * Unsigned 32-bit value indicating the packet filter size including * program + data. */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE, /* Unsigned 32-bit value indicating the packet filter current offset */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET, /* Program and/or data in bytes */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM, /* Unsigned 32-bit value of the length of the program section in packet * filter buffer. */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH = 7, /* keep last */ QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX = QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_drv_info - WLAN driver info used by vendor command * QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE. */ enum qca_wlan_vendor_drv_info { QCA_WLAN_VENDOR_ATTR_DRV_INFO_INVALID = 0, /* Maximum Message size info between firmware & HOST * Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE, /* keep last */ QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX = QCA_WLAN_VENDOR_ATTR_DRV_INFO_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_wake_stats - Wake lock stats used by vendor * command QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS. */ enum qca_wlan_vendor_attr_wake_stats { QCA_WLAN_VENDOR_ATTR_WAKE_STATS_INVALID = 0, /* Unsigned 32-bit value indicating the total count of wake event */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE, /* Array of individual wake count, each index representing wake reason */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR, /* Unsigned 32-bit value representing wake count array */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, /* Unsigned 32-bit total wake count value of driver/fw */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE, /* Array of wake stats of driver/fw */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR, /* Unsigned 32-bit total wake count value of driver/fw */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, /* Unsigned 32-bit total wake count value of packets received */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE, /* Unsigned 32-bit wake count value unicast packets received */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT, /* Unsigned 32-bit wake count value multicast packets received */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT, /* Unsigned 32-bit wake count value broadcast packets received */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT, /* Unsigned 32-bit wake count value of ICMP packets */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT, /* Unsigned 32-bit wake count value of ICMP6 packets */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT, /* Unsigned 32-bit value ICMP6 router advertisement */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA, /* Unsigned 32-bit value ICMP6 neighbor advertisement */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA, /* Unsigned 32-bit value ICMP6 neighbor solicitation */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS, /* Unsigned 32-bit wake count value of receive side ICMP4 multicast */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT, /* Unsigned 32-bit wake count value of receive side ICMP6 multicast */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT, /* Unsigned 32-bit wake count value of receive side multicast */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT, /* Unsigned 32-bit wake count value of a given RSSI breach */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RSSI_BREACH_CNT, /* Unsigned 32-bit wake count value of low RSSI */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_LOW_RSSI_CNT, /* Unsigned 32-bit value GSCAN count */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_GSCAN_CNT, /* Unsigned 32-bit value PNO complete count */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_COMPLETE_CNT, /* Unsigned 32-bit value PNO match count */ QCA_WLAN_VENDOR_ATTR_WAKE_STATS_PNO_MATCH_CNT, /* keep last */ QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST, QCA_WLAN_VENDOR_GET_WAKE_STATS_MAX = QCA_WLAN_VENDOR_GET_WAKE_STATS_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_thermal_level - Defines various thermal levels * configured by userspace to the driver/firmware. * The values can be encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL or * QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL attribute. * The driver/firmware takes actions requested by userspace such as throttling * wifi TX etc. in order to mitigate high temperature. * * @QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE: Stop/clear all throttling actions. * @QCA_WLAN_VENDOR_THERMAL_LEVEL_LIGHT: Throttle TX lightly. * @QCA_WLAN_VENDOR_THERMAL_LEVEL_MODERATE: Throttle TX moderately. * @QCA_WLAN_VENDOR_THERMAL_LEVEL_SEVERE: Throttle TX severely. * @QCA_WLAN_VENDOR_THERMAL_LEVEL_CRITICAL: Critical thermal level reached. * @QCA_WLAN_VENDOR_THERMAL_LEVEL_EMERGENCY: Emergency thermal level reached. */ enum qca_wlan_vendor_thermal_level { QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE = 0, QCA_WLAN_VENDOR_THERMAL_LEVEL_LIGHT = 1, QCA_WLAN_VENDOR_THERMAL_LEVEL_MODERATE = 2, QCA_WLAN_VENDOR_THERMAL_LEVEL_SEVERE = 3, QCA_WLAN_VENDOR_THERMAL_LEVEL_CRITICAL = 4, QCA_WLAN_VENDOR_THERMAL_LEVEL_EMERGENCY = 5, }; /** * enum qca_wlan_vendor_attr_thermal_cmd - Vendor subcmd attributes to set * cmd value. Used for NL attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command. */ enum qca_wlan_vendor_attr_thermal_cmd { QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_INVALID = 0, /* The value of command, driver will implement different operations * according to this value. It uses values defined in * enum qca_wlan_vendor_attr_thermal_cmd_type. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1, /* Userspace uses this attribute to configure thermal level to the * driver/firmware, or get thermal level from the driver/firmware. * Used in request or response, u32 attribute, * possible values are defined in enum qca_wlan_vendor_thermal_level. */ QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL = 2, /* Userspace uses this attribute to configure the time in which the * driver/firmware should complete applying settings it received from * userspace with QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL * command type. Used in request, u32 attribute, value is in * milliseconds. A value of zero indicates to apply the settings * immediately. The driver/firmware can delay applying the configured * thermal settings within the time specified in this attribute if * there is any critical ongoing operation. */ QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW = 3, /* Nested attribute, the driver/firmware uses this attribute to report * thermal statistics of different thermal levels to userspace when * requested using the * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS command * type. This attribute contains a nested array of records of thermal * statistics of multiple levels. The attributes used inside this nested * attribute are defined in enum qca_wlan_vendor_attr_thermal_stats. */ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX = QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_AFTER_LAST - 1 }; /** * qca_wlan_vendor_attr_thermal_cmd_type: Attribute values for * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE to the vendor subcmd * QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD. This represents the * thermal command types sent to driver. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS: Request to * get thermal shutdown configuration parameters for display. Parameters * responded from driver are defined in * enum qca_wlan_vendor_attr_get_thermal_params_rsp. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE: Request to * get temperature. Host should respond with a temperature data. It is defined * in enum qca_wlan_vendor_attr_thermal_get_temperature. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND: Request to execute thermal * suspend action. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME: Request to execute thermal * resume action. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: Configure thermal level to * the driver/firmware. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current * thermal level from the driver/firmware. The driver should respond with a * thermal level defined in enum qca_wlan_vendor_thermal_level. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS: Request to get the * current thermal statistics from the driver/firmware. The driver should * respond with statistics of all thermal levels encapsulated in the attribute * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS: Request to clear * the current thermal statistics for all thermal levels maintained in the * driver/firmware and start counting from zero again. */ enum qca_wlan_vendor_attr_thermal_cmd_type { QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_THERMAL_STATS, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_CLEAR_THERMAL_STATS, }; /** * enum qca_wlan_vendor_attr_thermal_get_temperature - vendor subcmd attributes * to get chip temperature by user. * enum values are used for NL attributes for data used by * QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_TEMPERATURE command for data used * by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command. */ enum qca_wlan_vendor_attr_thermal_get_temperature { QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_INVALID = 0, /* Temperature value (degree Celsius) from driver. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_DATA, /* keep last */ QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_MAX = QCA_WLAN_VENDOR_ATTR_THERMAL_GET_TEMPERATURE_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_get_thermal_params_rsp - vendor subcmd attributes * to get configuration parameters of thermal shutdown feature. Enum values are * used by QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS command for data * used by QCA_NL80211_VENDOR_SUBCMD_THERMAL_CMD sub command. */ enum qca_wlan_vendor_attr_get_thermal_params_rsp { QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_INVALID = 0, /* Indicate if the thermal shutdown feature is enabled. * NLA_FLAG attribute. */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_EN, /* Indicate if the auto mode is enabled. * Enable: Driver triggers the suspend/resume action. * Disable: User space triggers the suspend/resume action. * NLA_FLAG attribute. */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SHUTDOWN_AUTO_EN, /* Thermal resume threshold (degree Celsius). Issue the resume command * if the temperature value is lower than this threshold. * u16 attribute. */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_RESUME_THRESH, /* Thermal warning threshold (degree Celsius). FW reports temperature * to driver if it's higher than this threshold. * u16 attribute. */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_WARNING_THRESH, /* Thermal suspend threshold (degree Celsius). Issue the suspend command * if the temperature value is higher than this threshold. * u16 attribute. */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SUSPEND_THRESH, /* FW reports temperature data periodically at this interval (ms). * u16 attribute. */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_SAMPLE_RATE, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_MAX = QCA_WLAN_VENDOR_ATTR_GET_THERMAL_PARAMS_RSP_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_thermal_event - vendor subcmd attributes to * report thermal events from driver to user space. * enum values are used for NL attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_THERMAL_EVENT sub command. */ enum qca_wlan_vendor_attr_thermal_event { QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_INVALID = 0, /* Temperature value (degree Celsius) from driver. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_TEMPERATURE, /* Indication of resume completion from power save mode. * NLA_FLAG attribute. */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE, /* Thermal level from the driver. * u32 attribute. Possible values are defined in * enum qca_wlan_vendor_thermal_level. */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_MAX = QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_thermal_stats - vendor subcmd attributes * to get thermal status from the driver/firmware. * enum values are used for NL attributes encapsulated inside the * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS nested attribute. * * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE: Minimum temperature * of a thermal level in Celsius. u32 size. * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE: Maximum temperature * of a thermal level in Celsius. u32 size. * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME: The total time spent on each * thermal level in milliseconds. u32 size. * QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER: Indicates the number * of times the temperature crossed into the temperature range defined by the * thermal level from both higher and lower directions. u32 size. */ enum qca_wlan_vendor_attr_thermal_stats { QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MIN_TEMPERATURE, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX_TEMPERATURE, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_DWELL_TIME, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_TEMP_LEVEL_COUNTER, /* keep last */ QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_MAX = QCA_WLAN_VENDOR_ATTR_THERMAL_STATS_AFTER_LAST - 1, }; /** * enum he_fragmentation_val - HE fragmentation support values * Indicates level of dynamic fragmentation that is supported by * a STA as a recipient. * HE fragmentation values are defined in IEEE P802.11ax/D2.0, 9.4.2.237.2 * (HE MAC Capabilities Information field) and are used in HE Capabilities * element to advertise the support. These values are validated in the driver * to check the device capability and advertised in the HE Capabilities * element. These values are used to configure testbed device to allow the * advertised hardware capabilities to be downgraded for testing purposes. * * @HE_FRAG_DISABLE: no support for dynamic fragmentation * @HE_FRAG_LEVEL1: support for dynamic fragments that are * contained within an MPDU or S-MPDU, no support for dynamic fragments * within an A-MPDU that is not an S-MPDU. * @HE_FRAG_LEVEL2: support for dynamic fragments that are * contained within an MPDU or S-MPDU and support for up to one dynamic * fragment for each MSDU, each A-MSDU if supported by the recipient, and * each MMPDU within an A-MPDU or multi-TID A-MPDU that is not an * MPDU or S-MPDU. * @HE_FRAG_LEVEL3: support for dynamic fragments that are * contained within an MPDU or S-MPDU and support for multiple dynamic * fragments for each MSDU and for each A-MSDU if supported by the * recipient within an A-MPDU or multi-TID AMPDU and up to one dynamic * fragment for each MMPDU in a multi-TID A-MPDU that is not an S-MPDU. */ enum he_fragmentation_val { HE_FRAG_DISABLE, HE_FRAG_LEVEL1, HE_FRAG_LEVEL2, HE_FRAG_LEVEL3, }; /** * enum he_mcs_config - HE MCS support configuration * * Configures the HE Tx/Rx MCS map in HE capability IE for given bandwidth. * These values are used in driver to configure the HE MCS map to advertise * Tx/Rx MCS map in HE capability and these values are applied for all the * streams supported by the device. To configure MCS for different bandwidths, * vendor command needs to be sent using this attribute with appropriate value. * For example, to configure HE_80_MCS_0_7, send vendor command using HE MCS * attribute with HE_80_MCS0_7. And to configure HE MCS for HE_160_MCS0_11 * send this command using HE MCS config attribute with value HE_160_MCS0_11. * These values are used to configure testbed device to allow the advertised * hardware capabilities to be downgraded for testing purposes. The enum values * are defined such that BIT[1:0] indicates the MCS map value. Values 3,7 and * 11 are not used as BIT[1:0] value is 3 which is used to disable MCS map. * These values are validated in the driver before setting the MCS map and * driver returns error if the input is other than these enum values. * * @HE_80_MCS0_7: support for HE 80/40/20 MHz MCS 0 to 7 * @HE_80_MCS0_9: support for HE 80/40/20 MHz MCS 0 to 9 * @HE_80_MCS0_11: support for HE 80/40/20 MHz MCS 0 to 11 * @HE_160_MCS0_7: support for HE 160 MHz MCS 0 to 7 * @HE_160_MCS0_9: support for HE 160 MHz MCS 0 to 9 * @HE_160_MCS0_11: support for HE 160 MHz MCS 0 to 11 * @HE_80P80_MCS0_7: support for HE 80p80 MHz MCS 0 to 7 * @HE_80P80_MCS0_9: support for HE 80p80 MHz MCS 0 to 9 * @HE_80P80_MCS0_11: support for HE 80p80 MHz MCS 0 to 11 */ enum he_mcs_config { HE_80_MCS0_7 = 0, HE_80_MCS0_9 = 1, HE_80_MCS0_11 = 2, HE_160_MCS0_7 = 4, HE_160_MCS0_9 = 5, HE_160_MCS0_11 = 6, HE_80P80_MCS0_7 = 8, HE_80P80_MCS0_9 = 9, HE_80P80_MCS0_11 = 10, }; /** * enum qca_wlan_ba_session_config - BA session configuration * * Indicates the configuration values for BA session configuration attribute. * * @QCA_WLAN_ADD_BA: Establish a new BA session with given configuration. * @QCA_WLAN_DELETE_BA: Delete the existing BA session for given TID. */ enum qca_wlan_ba_session_config { QCA_WLAN_ADD_BA = 1, QCA_WLAN_DELETE_BA = 2, }; /** * enum qca_wlan_ac_type - Access category type * * Indicates the access category type value. * * @QCA_WLAN_AC_BE: BE access category * @QCA_WLAN_AC_BK: BK access category * @QCA_WLAN_AC_VI: VI access category * @QCA_WLAN_AC_VO: VO access category * @QCA_WLAN_AC_ALL: All ACs */ enum qca_wlan_ac_type { QCA_WLAN_AC_BE = 0, QCA_WLAN_AC_BK = 1, QCA_WLAN_AC_VI = 2, QCA_WLAN_AC_VO = 3, QCA_WLAN_AC_ALL = 4, }; /** * enum qca_wlan_he_ltf_cfg - HE LTF configuration * * Indicates the HE LTF configuration value. * * @QCA_WLAN_HE_LTF_AUTO: HE-LTF is automatically set to the mandatory HE-LTF, * based on the GI setting * @QCA_WLAN_HE_LTF_1X: 1X HE LTF is 3.2us LTF * @QCA_WLAN_HE_LTF_2X: 2X HE LTF is 6.4us LTF * @QCA_WLAN_HE_LTF_4X: 4X HE LTF is 12.8us LTF */ enum qca_wlan_he_ltf_cfg { QCA_WLAN_HE_LTF_AUTO = 0, QCA_WLAN_HE_LTF_1X = 1, QCA_WLAN_HE_LTF_2X = 2, QCA_WLAN_HE_LTF_4X = 3, }; /** * enum qca_wlan_he_mac_padding_dur - HE trigger frame MAC padding duration * * Indicates the HE trigger frame MAC padding duration value. * * @QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME: no additional time required to * process the trigger frame. * @QCA_WLAN_HE_8US_OF_PROCESS_TIME: indicates the 8us of processing time for * trigger frame. * @QCA_WLAN_HE_16US_OF_PROCESS_TIME: indicates the 16us of processing time for * trigger frame. */ enum qca_wlan_he_mac_padding_dur { QCA_WLAN_HE_NO_ADDITIONAL_PROCESS_TIME = 0, QCA_WLAN_HE_8US_OF_PROCESS_TIME = 1, QCA_WLAN_HE_16US_OF_PROCESS_TIME = 2, }; /** * enum qca_wlan_he_om_ctrl_ch_bw - HE OM control field BW configuration * * Indicates the HE Operating mode control channel width setting value. * * @QCA_WLAN_HE_OM_CTRL_BW_20M: Primary 20 MHz * @QCA_WLAN_HE_OM_CTRL_BW_40M: Primary 40 MHz * @QCA_WLAN_HE_OM_CTRL_BW_80M: Primary 80 MHz * @QCA_WLAN_HE_OM_CTRL_BW_160M: 160 MHz and 80+80 MHz */ enum qca_wlan_he_om_ctrl_ch_bw { QCA_WLAN_HE_OM_CTRL_BW_20M = 0, QCA_WLAN_HE_OM_CTRL_BW_40M = 1, QCA_WLAN_HE_OM_CTRL_BW_80M = 2, QCA_WLAN_HE_OM_CTRL_BW_160M = 3, }; /** * enum qca_wlan_keep_alive_data_type - Keep alive data type configuration * * Indicates the frame types to use for keep alive data. * * @QCA_WLAN_KEEP_ALIVE_DEFAULT: Driver default type used for keep alive. * @QCA_WLAN_KEEP_ALIVE_DATA: Data frame type for keep alive. * @QCA_WLAN_KEEP_ALIVE_MGMT: Management frame type for keep alive. */ enum qca_wlan_keep_alive_data_type { QCA_WLAN_KEEP_ALIVE_DEFAULT = 0, QCA_WLAN_KEEP_ALIVE_DATA = 1, QCA_WLAN_KEEP_ALIVE_MGMT = 2, }; /** * enum qca_wlan_vendor_attr_he_omi_tx: Represents attributes for * HE operating mode control transmit request. These attributes are * sent as part of QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX and * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. * * @QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS: Mandatory 8-bit unsigned value * indicates the maximum number of spatial streams, NSS, that the STA * supports in reception for PPDU bandwidths less than or equal to 80 MHz * and is set to NSS - 1. * * @QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW: Mandatory 8-bit unsigned value * indicates the operating channel width supported by the STA for both * reception and transmission. Uses enum qca_wlan_he_om_ctrl_ch_bw values. * * @QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE: Mandatory 8-bit unsigned value * indicates the all trigger based UL MU operations by the STA. * 0 - UL MU operations are enabled by the STA. * 1 - All triggered UL MU transmissions are suspended by the STA. * * @QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS: Mandatory 8-bit unsigned value * indicates the maximum number of space-time streams, NSTS, that * the STA supports in transmission and is set to NSTS - 1. * * @QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE: 8-bit unsigned value * combined with the UL MU Disable subfield and the recipient's setting * of the OM Control UL MU Data Disable RX Support subfield in the HE MAC * capabilities to determine which HE TB PPDUs are possible by the * STA to transmit. * 0 - UL MU data operations are enabled by the STA. * 1 - Determine which HE TB PPDU types are allowed by the STA if UL MU disable * bit is not set, else UL MU Tx is suspended. * */ enum qca_wlan_vendor_attr_he_omi_tx { QCA_WLAN_VENDOR_ATTR_HE_OMI_INVALID = 0, QCA_WLAN_VENDOR_ATTR_HE_OMI_RX_NSS = 1, QCA_WLAN_VENDOR_ATTR_HE_OMI_CH_BW = 2, QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DISABLE = 3, QCA_WLAN_VENDOR_ATTR_HE_OMI_TX_NSTS = 4, QCA_WLAN_VENDOR_ATTR_HE_OMI_ULMU_DATA_DISABLE = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HE_OMI_MAX = QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_phy_mode - Different PHY modes * These values are used with %QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE. * * @QCA_WLAN_VENDOR_PHY_MODE_AUTO: autoselect * @QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO: 2.4 GHz 802.11b/g/n/ax autoselect * @QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO: 5 GHz 802.11a/n/ac/ax autoselect * @QCA_WLAN_VENDOR_PHY_MODE_11A: 5 GHz, OFDM * @QCA_WLAN_VENDOR_PHY_MODE_11B: 2.4 GHz, CCK * @QCA_WLAN_VENDOR_PHY_MODE_11G: 2.4 GHz, OFDM * @QCA_WLAN_VENDOR_PHY_MODE_11AGN: Support 802.11n in both 2.4 GHz and 5 GHz * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20: 2.4 GHz, HT20 * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS: 2.4 GHz, HT40 (ext ch +1) * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS: 2.4 GHz, HT40 (ext ch -1) * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40: 2.4 GHz, Auto HT40 * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20: 5 GHz, HT20 * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS: 5 GHz, HT40 (ext ch +1) * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS: 5 GHz, HT40 (ext ch -1) * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40: 5 GHz, Auto HT40 * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20: 5 GHz, VHT20 * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS: 5 GHz, VHT40 (Ext ch +1) * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS: 5 GHz VHT40 (Ext ch -1) * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40: 5 GHz, VHT40 * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80: 5 GHz, VHT80 * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80: 5 GHz, VHT80+80 * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160: 5 GHz, VHT160 * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20: HE20 * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40: HE40 * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS: HE40 (ext ch +1) * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS: HE40 (ext ch -1) * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80: HE80 * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80: HE 80P80 * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160: HE160 */ enum qca_wlan_vendor_phy_mode { QCA_WLAN_VENDOR_PHY_MODE_AUTO = 0, QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO = 1, QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO = 2, QCA_WLAN_VENDOR_PHY_MODE_11A = 3, QCA_WLAN_VENDOR_PHY_MODE_11B = 4, QCA_WLAN_VENDOR_PHY_MODE_11G = 5, QCA_WLAN_VENDOR_PHY_MODE_11AGN = 6, QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20 = 7, QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS = 8, QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS = 9, QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40 = 10, QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20 = 11, QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS = 12, QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS = 13, QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40 = 14, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20 = 15, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS = 16, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS = 17, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40 = 18, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80 = 19, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80 = 20, QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160 = 21, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20 = 22, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40 = 23, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS = 24, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS = 25, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80 = 26, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80 = 27, QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160 = 28, }; /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION */ enum qca_wlan_vendor_attr_wifi_test_config { QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_INVALID = 0, /* 8-bit unsigned value to configure the driver to enable/disable * WMM feature. This attribute is used to configure testbed device. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WMM_ENABLE = 1, /* 8-bit unsigned value to configure the driver to accept/reject * the addba request from peer. This attribute is used to configure * the testbed device. * 1-accept addba, 0-reject addba */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ACCEPT_ADDBA_REQ = 2, /* 8-bit unsigned value to configure the driver to send or not to * send the addba request to peer. * This attribute is used to configure the testbed device. * 1-send addba, 0-do not send addba */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ = 3, /* 8-bit unsigned value to indicate the HE fragmentation support. * Uses enum he_fragmentation_val values. * This attribute is used to configure the testbed device to * allow the advertised hardware capabilities to be downgraded * for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_FRAGMENTATION = 4, /* 8-bit unsigned value to indicate the HE MCS support. * Uses enum he_mcs_config values. * This attribute is used to configure the testbed device to * allow the advertised hardware capabilities to be downgraded * for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MCS = 5, /* 8-bit unsigned value to configure the driver to allow or not to * allow the connection with WEP/TKIP in HT/VHT/HE modes. * This attribute is used to configure the testbed device. * 1-allow WEP/TKIP in HT/VHT/HE, 0-do not allow WEP/TKIP. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_WEP_TKIP_IN_HE = 6, /* 8-bit unsigned value to configure the driver to add a * new BA session or delete the existing BA session for * given TID. ADDBA command uses the buffer size and TID * configuration if user specifies the values else default * value for buffer size is used for all TIDs if the TID * also not specified. For DEL_BA command TID value is * required to process the command. * Uses enum qca_wlan_ba_session_config values. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADD_DEL_BA_SESSION = 7, /* 16-bit unsigned value to configure the buffer size in addba * request and response frames. * This attribute is used to configure the testbed device. * The range of the value is 0 to 256. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE = 8, /* 8-bit unsigned value to configure the buffer size in addba * request and response frames. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BA_TID = 9, /* 8-bit unsigned value to configure the no ack policy. * To configure no ack policy, access category value is * required to process the command. * This attribute is used to configure the testbed device. * 1 - enable no ack, 0 - disable no ack. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK = 10, /* 8-bit unsigned value to configure the AC for no ack policy * This attribute is used to configure the testbed device. * Uses the enum qca_wlan_ac_type values. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_NO_ACK_AC = 11, /* 8-bit unsigned value to configure the HE LTF * This attribute is used to configure the testbed device. * Uses the enum qca_wlan_he_ltf_cfg values. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_LTF = 12, /* 8-bit unsigned value to configure the tx beamformee. * This attribute is used to configure the testbed device. * 1-enable, 0-disable. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_TX_BEAMFORMEE = 13, /* 8-bit unsigned value to configure the tx beamformee number * of space-time streams. * This attribute is used to configure the testbed device. * The range of the value is 0 to 8. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_BEAMFORMEE_NSTS = 14, /* 8-bit unsigned value to configure the MU EDCA params for given AC * This attribute is used to configure the testbed device. * Uses the enum qca_wlan_ac_type values. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AC = 15, /* 8-bit unsigned value to configure the MU EDCA AIFSN for given AC * To configure MU EDCA AIFSN value, MU EDCA access category value * is required to process the command. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_AIFSN = 16, /* 8-bit unsigned value to configure the MU EDCA ECW min value for * given AC. * To configure MU EDCA ECW min value, MU EDCA access category value * is required to process the command. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMIN = 17, /* 8-bit unsigned value to configure the MU EDCA ECW max value for * given AC. * To configure MU EDCA ECW max value, MU EDCA access category value * is required to process the command. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_ECWMAX = 18, /* 8-bit unsigned value to configure the MU EDCA timer for given AC * To configure MU EDCA timer value, MU EDCA access category value * is required to process the command. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MU_EDCA_TIMER = 19, /* 8-bit unsigned value to configure the HE trigger frame MAC padding * duration. * This attribute is used to configure the testbed device. * Uses the enum qca_wlan_he_mac_padding_dur values. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_MAC_PADDING_DUR = 20, /* 8-bit unsigned value to override the MU EDCA params to defaults * regardless of the AP beacon MU EDCA params. If it is enabled use * the default values else use the MU EDCA params from AP beacon. * This attribute is used to configure the testbed device. * 1-enable, 0-disable. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OVERRIDE_MU_EDCA = 21, /* 8-bit unsigned value to configure the support for receiving * an MPDU that contains an operating mode control subfield. * This attribute is used to configure the testbed device. * 1-enable, 0-disable. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_SUPP = 22, /* Nested attribute values required to setup the TWT session. * enum qca_wlan_vendor_attr_twt_setup provides the necessary * information to set up the session. It contains broadcast flags, * set_up flags, trigger value, flow type, flow ID, wake interval * exponent, protection, target wake time, wake duration, wake interval * mantissa. These nested attributes are used to setup a host triggered * TWT session. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP = 23, /* This nested attribute is used to terminate the current TWT session. * It does not currently carry any attributes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_TERMINATE = 24, /* This nested attribute is used to suspend the current TWT session. * It does not currently carry any attributes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SUSPEND = 25, /* Nested attribute values to indicate the request for resume. * This attribute is used to resume the TWT session. * enum qca_wlan_vendor_attr_twt_resume provides the necessary * parameters required to resume the TWT session. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME = 26, /* 8-bit unsigned value to set the HE operating mode control * (OM CTRL) Channel Width subfield. * The Channel Width subfield indicates the operating channel width * supported by the STA for both reception and transmission. * Uses the enum qca_wlan_he_om_ctrl_ch_bw values. * This setting is cleared with the * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG * flag attribute to reset defaults. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW = 27, /* 8-bit unsigned value to configure the number of spatial * streams in HE operating mode control field. * This setting is cleared with the * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG * flag attribute to reset defaults. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS = 28, /* Flag attribute to configure the UL MU disable bit in * HE operating mode control field. * This setting is cleared with the * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG * flag attribute to reset defaults. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_UL_MU_DISABLE = 29, /* Flag attribute to clear the previously set HE operating mode * control field configuration. * This attribute is used to configure the testbed device to reset * defaults to clear any previously set HE operating mode control * field configuration. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG = 30, /* 8-bit unsigned value to configure HE single user PPDU * transmission. By default this setting is disabled and it * is disabled in the reset defaults of the device configuration. * This attribute is used to configure the testbed device. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU = 31, /* 8-bit unsigned value to configure action frame transmission * in HE trigger based PPDU transmission. * By default this setting is disabled and it is disabled in * the reset defaults of the device configuration. * This attribute is used to configure the testbed device. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU = 32, /* Nested attribute to indicate HE operating mode control field * transmission. It contains operating mode control field Nss, * channel bandwidth, Tx Nsts and UL MU disable attributes. * These nested attributes are used to send HE operating mode control * with configured values. * Uses the enum qca_wlan_vendor_attr_he_omi_tx attributes. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OMI_TX = 33, /* 8-bit unsigned value to configure +HTC_HE support to indicate the * support for the reception of a frame that carries an HE variant * HT Control field. * This attribute is used to configure the testbed device. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_HTC_HE_SUPP = 34, /* 8-bit unsigned value to configure VHT support in 2.4G band. * This attribute is used to configure the testbed device. * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_2G_VHT = 35, /* 8-bit unsigned value to configure HE testbed defaults. * This attribute is used to configure the testbed device. * 1-set the device HE capabilities to testbed defaults. * 0-reset the device HE capabilities to supported config. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SET_HE_TESTBED_DEFAULTS = 36, /* 8-bit unsigned value to configure TWT request support. * This attribute is used to configure the testbed device. * 1-enable, 0-disable. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT = 37, /* 8-bit unsigned value to configure protection for Management * frames when PMF is enabled for the association. * This attribute is used to configure the testbed device. * 0-use the correct key, 1-use an incorrect key, 2-disable protection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION = 38, /* Flag attribute to inject Disassociation frame to the connected AP. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX = 39, /* 8-bit unsigned value to configure an override for the RSNXE Used * subfield in the MIC control field of the FTE in FT Reassociation * Request frame. * 0 - Default behavior, 1 - override with 1, 2 - override with 0. * This attribute is used to configure the testbed device. * This attribute can be configured only when STA is in associated state * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED = 40, /* 8-bit unsigned value to configure the driver to ignore CSA (Channel * Switch Announcement) when STA is in connected state. * 0 - Default behavior, 1 - Ignore CSA. * This attribute is used to configure the testbed device. * This attribute can be configured only when STA is in associated state * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA = 41, /* Nested attribute values required to configure OCI (Operating Channel * Information). Attributes defined in enum * qca_wlan_vendor_attr_oci_override are nested within this attribute. * This attribute is used to configure the testbed device. * This attribute can be configured only when STA is in associated state * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE = 42, /* 8-bit unsigned value to configure the driver/firmware to ignore SA * Query timeout. If this configuration is enabled STA shall not send * Deauthentication frmae when SA Query times out (mainly, after a * channel switch when OCV is enabled). * 0 - Default behavior, 1 - Ignore SA Query timeout. * This attribute is used to configure the testbed device. * This attribute can be configured only when STA is in associated state * and the configuration is valid until the disconnection. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43, /* 8-bit unsigned value to configure the driver/firmware to start or * stop transmitting FILS discovery frames. * 0 - Stop transmitting FILS discovery frames * 1 - Start transmitting FILS discovery frames * This attribute is used to configure the testbed device. * This attribute can be configured only in AP mode and the * configuration is valid until AP restart. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44, /* 8-bit unsigned value to configure the driver/firmware to enable or * disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities * information field. * 0 - Disable full bandwidth UL MU-MIMO subfield * 1 - Enable full bandwidth UL MU-MIMO subfield * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO = 45, /* 16-bit unsigned value to configure the driver with a specific BSS * max idle period to advertise in the BSS Max Idle Period element * (IEEE Std 802.11-2016, 9.4.2.79) in (Re)Association Request frames. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD = 46, /* 8-bit unsigned value to configure the driver to use only RU 242 tone * for data transmission. * 0 - Default behavior, 1 - Configure RU 242 tone for data Tx. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RU_242_TONE_TX = 47, /* 8-bit unsigned value to configure the driver to disable data and * management response frame transmission to test the BSS max idle * feature. * 0 - Default behavior, 1 - Disable data and management response Tx. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISABLE_DATA_MGMT_RSP_TX = 48, /* 8-bit unsigned value to configure the driver/firmware to enable or * disable Punctured Preamble Rx subfield in the HE PHY capabilities * information field. * 0 - Disable Punctured Preamble Rx subfield * 1 - Enable Punctured Preamble Rx subfield * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PUNCTURED_PREAMBLE_RX = 49, /* 8-bit unsigned value to configure the driver to ignore the SAE H2E * requirement mismatch for 6 GHz connection. * 0 - Default behavior, 1 - Ignore SAE H2E requirement mismatch. * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_H2E_RSNXE = 50, /* 8-bit unsigned value to configure the driver to allow 6 GHz * connection with all security modes. * 0 - Default behavior, 1 - Allow 6 GHz connection with all security * modes. * This attribute is used for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_6GHZ_SECURITY_TEST_MODE = 51, /* 8-bit unsigned value to configure the driver to transmit data with * ER SU PPDU type. * * 0 - Default behavior, 1 - Enable ER SU PPDU type TX. * This attribute is used for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ER_SU_PPDU_TYPE = 52, /* 8-bit unsigned value to configure the driver to use Data or * Management frame type for keep alive data. * Uses enum qca_wlan_keep_alive_data_type values. * * This attribute is used for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_KEEP_ALIVE_FRAME_TYPE = 53, /* 8-bit unsigned value to configure the driver to use scan request * BSSID value in Probe Request frame RA(A1) during the scan. The * driver saves this configuration and applies this setting to all user * space scan requests until the setting is cleared. If this * configuration is set, the driver uses the BSSID value from the scan * request to set the RA(A1) in the Probe Request frames during the * scan. * * 0 - Default behavior uses the broadcast RA in Probe Request frames. * 1 - Uses the scan request BSSID in RA in Probe Request frames. * This attribute is used for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_USE_BSSID_IN_PROBE_REQ_RA = 54, /* 8-bit unsigned value to configure the driver to enable/disable the * BSS max idle period support. * * 0 - Disable the BSS max idle support. * 1 - Enable the BSS max idle support. * This attribute is used for testing purposes. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BSS_MAX_IDLE_PERIOD_ENABLE = 55, /* 8-bit unsigned value to configure the driver/firmware to enable or * disable Rx control frame to MultiBSS subfield in the HE MAC * capabilities information field. * 0 - Disable Rx control frame to MultiBSS subfield * 1 - Enable Rx control frame to MultiBSS subfield * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_RX_CTRL_FRAME_TO_MBSS = 56, /* 8-bit unsigned value to configure the driver/firmware to enable or * disable Broadcast TWT support subfield in the HE MAC capabilities * information field. * 0 - Disable Broadcast TWT support subfield * 1 - Enable Broadcast TWT support subfield * This attribute is used to configure the testbed device. */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_BCAST_TWT_SUPPORT = 57, /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1, }; /** * enum qca_wlan_twt_operation - Operation of the config TWT request * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION. * The response for the respective operations can be either synchronous or * asynchronous (wherever specified). If synchronous, the response to this * operation is obtained in the corresponding vendor command reply to the user * space. For the asynchronous case the response is obtained as an event with * the same operation type. * * Drivers shall support either of these modes but not both simultaneously. * This support for asynchronous mode is advertised through the flag * QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT. If this flag is not advertised, * the driver shall support synchronous mode. * * @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured * through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_setup. Depending upon the * @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability, this is either a * synchronous or asynchronous operation. * * @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_setup. This is a synchronous operation. * * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. * This terminate can either get triggered by the user space or can as well be * a notification from the firmware if it initiates a terminate. * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability, * the request from user space can either be a synchronous or asynchronous * operation. * * @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. * Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT capability, * this is either a synchronous or asynchronous operation. * * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum * qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup. * This can as well be a notification from the firmware on a QCA_WLAN_TWT_NUDGE * request. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT * capability, this is either a synchronous or asynchronous operation. * * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a * combination of suspend and resume in a single request. Required parameters * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is * setup. Depending upon the @QCA_WLAN_VENDOR_FEATURE_TWT_ASYNC_SUPPORT * capability, this is either a synchronous or asynchronous operation. * * @QCA_WLAN_TWT_GET_STATS: Get the TWT session traffic statistics information. * Refers the enum qca_wlan_vendor_attr_twt_stats. Valid only after the TWT * session is setup. It's a synchronous operation. * * @QCA_WLAN_TWT_CLEAR_STATS: Clear TWT session traffic statistics information. * Valid only after the TWT session is setup. It's a synchronous operation. * * @QCA_WLAN_TWT_GET_CAPABILITIES: Get TWT capabilities of this device and its * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous * operation. * * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is * ready for a new TWT session setup after it issued a TWT teardown. * * @QCA_WLAN_TWT_SET_PARAM: Configure TWT related parameters. Required * parameters are obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refer * the enum qca_wlan_vendor_attr_twt_set_param. */ enum qca_wlan_twt_operation { QCA_WLAN_TWT_SET = 0, QCA_WLAN_TWT_GET = 1, QCA_WLAN_TWT_TERMINATE = 2, QCA_WLAN_TWT_SUSPEND = 3, QCA_WLAN_TWT_RESUME = 4, QCA_WLAN_TWT_NUDGE = 5, QCA_WLAN_TWT_GET_STATS = 6, QCA_WLAN_TWT_CLEAR_STATS = 7, QCA_WLAN_TWT_GET_CAPABILITIES = 8, QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9, QCA_WLAN_TWT_SET_PARAM = 10, }; /** * enum qca_wlan_vendor_attr_config_twt: Defines attributes used by * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION: u8 attribute. Specify the TWT * operation of this request. Possible values are defined in enum * qca_wlan_twt_operation. The parameters for the respective operation is * specified through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the * parameters configured for TWT. These parameters are represented by * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume, * enum qca_wlan_vendor_attr_twt_set_param, or * enum qca_wlan_vendor_attr_twt_stats based on the operation. */ enum qca_wlan_vendor_attr_config_twt { QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION = 1, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX = QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_bss_filter - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. * The user can add/delete the filter by specifying the BSSID/STA MAC address in * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, filter type in * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, add/delete action in * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user can get the * statistics of an unassociated station by specifying the MAC address in * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR, station type in * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE, GET action in * QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION in the request. The user also can get * the statistics of all unassociated stations by specifying the Broadcast MAC * address (ff:ff:ff:ff:ff:ff) in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR with * above procedure. In the response, driver shall specify statistics * information nested in QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS. */ enum qca_wlan_vendor_attr_bss_filter { QCA_WLAN_VENDOR_ATTR_BSS_FILTER_INVALID = 0, QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAC_ADDR = 1, /* Other BSS filter type, unsigned 8 bit value. One of the values * in enum qca_wlan_vendor_bss_filter_type. */ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_TYPE = 2, /* Other BSS filter action, unsigned 8 bit value. One of the values * in enum qca_wlan_vendor_bss_filter_action. */ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_ACTION = 3, /* Array of nested attributes where each entry is the statistics * information of the specified station that belong to another BSS. * Attributes for each entry are taken from enum * qca_wlan_vendor_bss_filter_sta_stats. * Other BSS station configured in * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER with filter type * QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA. * Statistics returned by QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER * with filter action QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET. */ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_STA_STATS = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_BSS_FILTER_MAX = QCA_WLAN_VENDOR_ATTR_BSS_FILTER_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_bss_filter_type - Type of * filter used in other BSS filter operations. Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. * * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID: BSSID filter * @QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA: Station MAC address filter */ enum qca_wlan_vendor_bss_filter_type { QCA_WLAN_VENDOR_BSS_FILTER_TYPE_BSSID, QCA_WLAN_VENDOR_BSS_FILTER_TYPE_STA, }; /** * enum qca_wlan_vendor_bss_filter_action - Type of * action in other BSS filter operations. Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. * * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD: Add filter * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL: Delete filter * @QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET: Get the statistics */ enum qca_wlan_vendor_bss_filter_action { QCA_WLAN_VENDOR_BSS_FILTER_ACTION_ADD, QCA_WLAN_VENDOR_BSS_FILTER_ACTION_DEL, QCA_WLAN_VENDOR_BSS_FILTER_ACTION_GET, }; /** * enum qca_wlan_vendor_bss_filter_sta_stats - Attributes for * the statistics of a specific unassociated station belonging to another BSS. * The statistics provides information of the unassociated station * filtered by other BSS operation - such as MAC, signal value. * Used by the vendor command QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. * * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC: MAC address of the station. * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI: Last received signal strength * of the station. Unsigned 8 bit number containing RSSI. * @QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS: Time stamp of the host * driver for the last received RSSI. Unsigned 64 bit number containing * nanoseconds from the boottime. */ enum qca_wlan_vendor_bss_filter_sta_stats { QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_INVALID = 0, QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAC = 1, QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI = 2, QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_RSSI_TS = 3, /* keep last */ QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST, QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_MAX = QCA_WLAN_VENDOR_BSS_FILTER_STA_STATS_AFTER_LAST - 1 }; /* enum qca_wlan_nan_subcmd_type - Type of NAN command used by attribute * QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE as a part of vendor command * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. */ enum qca_wlan_nan_ext_subcmd_type { /* Subcmd of type NAN Enable Request */ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ = 1, /* Subcmd of type NAN Disable Request */ QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ = 2, }; /** * enum qca_wlan_vendor_attr_nan_params - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. */ enum qca_wlan_vendor_attr_nan_params { QCA_WLAN_VENDOR_ATTR_NAN_INVALID = 0, /* Carries NAN command for firmware component. Every vendor command * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT must contain this attribute with a * payload containing the NAN command. NLA_BINARY attribute. */ QCA_WLAN_VENDOR_ATTR_NAN_CMD_DATA = 1, /* Indicates the type of NAN command sent with * QCA_NL80211_VENDOR_SUBCMD_NAN_EXT. enum qca_wlan_nan_ext_subcmd_type * describes the possible range of values. This attribute is mandatory * if the command being issued is either * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ or * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_DISABLE_REQ. NLA_U32 attribute. */ QCA_WLAN_VENDOR_ATTR_NAN_SUBCMD_TYPE = 2, /* Frequency (in MHz) of primary NAN discovery social channel in 2.4 GHz * band. This attribute is mandatory when command type is * QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ. NLA_U32 attribute. */ QCA_WLAN_VENDOR_ATTR_NAN_DISC_24GHZ_BAND_FREQ = 3, /* Frequency (in MHz) of secondary NAN discovery social channel in 5 GHz * band. This attribute is optional and should be included when command * type is QCA_WLAN_NAN_EXT_SUBCMD_TYPE_ENABLE_REQ and NAN discovery * has to be started on 5GHz along with 2.4GHz. NLA_U32 attribute. */ QCA_WLAN_VENDOR_ATTR_NAN_DISC_5GHZ_BAND_FREQ = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_MAX = QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST - 1 }; /** * qca_wlan_twt_setup_state: Represents the TWT session states. * * QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED: TWT session not established. * QCA_WLAN_TWT_SETUP_STATE_ACTIVE: TWT session is active. * QCA_WLAN_TWT_SETUP_STATE_SUSPEND: TWT session is in suspended state. */ enum qca_wlan_twt_setup_state { QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED = 0, QCA_WLAN_TWT_SETUP_STATE_ACTIVE = 1, QCA_WLAN_TWT_SETUP_STATE_SUSPEND = 2, }; /** * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for * TWT (Target Wake Time) setup request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute. * Disable (flag attribute not present) - Individual TWT * Enable (flag attribute present) - Broadcast TWT. * Individual means the session is between the STA and the AP. * This session is established using a separate negotiation between * STA and AP. * Broadcast means the session is across multiple STAs and an AP. The * configuration parameters are announced in Beacon frames by the AP. * This is used in * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE: Required (u8). * Unsigned 8-bit qca_wlan_vendor_twt_setup_req_type to * specify the TWT request type. This is used in TWT SET operation. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER: Flag attribute * Enable (flag attribute present) - TWT with trigger support. * Disable (flag attribute not present) - TWT without trigger support. * Trigger means the AP will send the trigger frame to allow STA to send data. * Without trigger, the STA will wait for the MU EDCA timer before * transmitting the data. * This is used in * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE: Required (u8) * 0 - Announced TWT - In this mode, STA may skip few service periods to * save more power. If STA wants to wake up, it will send a PS-POLL/QoS * NULL frame to AP. * 1 - Unannounced TWT - The STA will wakeup during every SP. * This is a required parameter for * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID: Optional (u8) * Flow ID is the unique identifier for each TWT session. * If not provided then dialog ID will be set to zero. * This is an optional parameter for * 1. TWT SET Request and Response * 2. TWT GET Request and Response * 3. TWT TERMINATE Request and Response * 4. TWT SUSPEND Request and Response * Flow ID values from 0 to 254 represent a single TWT session * Flow ID value of 255 represents all TWT sessions for the following * 1. TWT TERMINATE Request and Response * 2. TWT SUSPEND Request and Response * 4. TWT CLEAR STATISTICS request * 5. TWT GET STATISTICS request and response * If an invalid dialog ID is provided, status * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8) * This attribute (exp) is used along with the mantissa to derive the * wake interval using the following formula: * pow(2,exp) = wake_intvl_us/wake_intvl_mantis * Wake interval is the interval between 2 successive SP. * This is a required parameter for * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION: Flag attribute * Enable (flag attribute present) - Protection required. * Disable (flag attribute not present) - Protection not required. * If protection is enabled, then the AP will use protection * mechanism using RTS/CTS to self to reserve the airtime. * This is used in * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME: Optional (u32) * This attribute is used as the SP offset which is the offset from * TSF after which the wake happens. The units are in microseconds. If * this attribute is not provided, then the value will be set to zero. * This is an optional parameter for * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION: Required (u32) * This is the duration of the service period. This is specified as * multiples of 256 microseconds. Valid values are 0x1 to 0xFF. * This is a required parameter for * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32) * This attribute is used to configure wake interval mantissa. * The units are in TU. * This is a required parameter for * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS: Required (u8) * This field is applicable for TWT response only. * This contains status values in enum qca_wlan_vendor_twt_status * and is passed to the userspace. This is used in TWT SET operation. * This is a required parameter for * 1. TWT SET Response * 2. TWT TERMINATE Response * 3. TWT SUSPEND Response * 4. TWT RESUME Response * 5. TWT NUDGE Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8) * This field is applicable for TWT response only. * This field contains response type from the TWT responder and is * passed to the userspace. The values for this field are defined in * enum qca_wlan_vendor_twt_setup_resp_type. This is used in TWT SET * response. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64) * In TWT setup command this field contains absolute TSF that will * be used by TWT requester during setup. * In TWT response this field contains absolute TSF value of the * wake time received from the TWT responder and is passed to * the userspace. * This is an optional parameter for * 1. TWT SET Request * This is a required parameter for * 1. TWT SET Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED: Flag attribute. * Enable (flag attribute present) - Indicates that the TWT responder * supports reception of TWT information frame from the TWT requestor. * Disable (flag attribute not present) - Indicates that the responder * doesn't support reception of TWT information frame from requestor. * This is used in * 1. TWT SET Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address * Represents the MAC address of the peer for which the TWT session * is being configured. This is used in AP mode to represent the respective * client. * In AP mode, this is a required parameter in response for * 1. TWT SET * 2. TWT GET * 3. TWT TERMINATE * 4. TWT SUSPEND * In STA mode, this is an optional parameter in request and response for * the above four TWT operations. * In AP mode, this is a required parameter in request for * 1. TWT GET * 2. TWT TERMINATE * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32) * Minimum tolerance limit of wake interval parameter in microseconds. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL: Optional (u32) * Maximum tolerance limit of wake interval parameter in microseconds. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION: Optional (u32) * Minimum tolerance limit of wake duration parameter in microseconds. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION: Optional (u32) * Maximum tolerance limit of wake duration parameter in microseconds. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE: Optional (u32) * TWT state for the given dialog id. The values for this are represented * by enum qca_wlan_twt_setup_state. * This is obtained through TWT GET operation. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA: Optional (u32) * This attribute is used to configure wake interval mantissa. * The unit is microseconds. This attribute, when specified, takes * precedence over QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA. * This parameter is used for * 1. TWT SET Request and Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID: Optional (u8) * This attribute is used to configure Broadcast TWT ID. * The Broadcast TWT ID indicates a specific Broadcast TWT for which the * transmitting STA is providing TWT parameters. The allowed values are 0 to 31. * This parameter is used for * 1. TWT SET Request * 2. TWT TERMINATE Request * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION: Optional (u8) * This attribute is used to configure Broadcast TWT recommendation. * The Broadcast TWT Recommendation subfield contains a value that indicates * recommendations on the types of frames that are transmitted by TWT * scheduled STAs and scheduling AP during the broadcast TWT SP. * The allowed values are 0 - 3. * This parameter is used for * 1. TWT SET Request * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE: Optional (u8) * This attribute is used to configure Broadcast TWT Persistence. * The Broadcast TWT Persistence subfield indicates the number of * TBTTs during which the Broadcast TWT SPs corresponding to this * broadcast TWT Parameter set are present. The number of beacon intervals * during which the Broadcast TWT SPs are present is equal to the value in the * Broadcast TWT Persistence subfield plus 1 except that the value 255 * indicates that the Broadcast TWT SPs are present until explicitly terminated. * This parameter is used for * 1. TWT SET Request * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE: Optional (u8) * This attribute contains the value of the Responder PM Mode subfield (0 or 1) * from TWT response frame. * This parameter is used for * 1. TWT SET Response * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT: Optional (u32) * This attribute is used to configure the announce timeout value (in us) in * the firmware. This timeout value is only applicable for the announced TWT. If * the timeout value is non-zero the firmware waits up to the timeout value to * use Data frame as an announcement frame. If the timeout value is 0 the * firmware sends an explicit QoS NULL frame as the announcement frame on SP * start. The default value in the firmware is 0. * This parameter is used for * 1. TWT SET Request */ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST = 1, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE = 2, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER = 3, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE = 4, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID = 5, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP = 6, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION = 7, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME = 8, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION = 9, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA = 10, /* TWT Response only attributes */ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS = 11, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE = 12, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF = 13, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL = 16, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL = 17, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION = 18, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL2_MANTISSA = 21, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_ID = 22, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_RECOMMENDATION = 23, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST_PERSISTENCE = 24, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESPONDER_PM_MODE = 25, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_ANNOUNCE_TIMEOUT = 26, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX = QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_twt_status - Represents the status of the requested * TWT operation * * @QCA_WLAN_VENDOR_TWT_STATUS_OK: TWT request successfully completed * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED: TWT not enabled * @QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID: TWT dialog ID is already used * @QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY: TWT session is busy * @QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST: TWT session does not exist * @QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED: TWT session not in suspend state * @QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM: Invalid parameters * @QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY: FW not ready * @QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE: FW resource exhausted * @QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK: Peer AP/STA did not ACK the * request/response frame * @QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE: Peer AP did not send the response * frame * @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request * @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an * unknown reason * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in * suspend state * @QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID: FW has dropped the frame due to * invalid IE in the received TWT frame * @QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE: Parameters received from * the responder are not in the specified range * @QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE: FW terminated the TWT * session due to request from the responder. Used on the TWT_TERMINATE * notification from the firmware. * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT * session due to roaming. Used on the TWT_TERMINATE notification from the * firmware. * @QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE: FW terminated the * TWT session due to SCC (Single Channel Concurrency) and MCC (Multi Channel * Concurrency). Used on the TWT_TERMINATE notification from the firmware. * @QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS: FW rejected the TWT setup * request due to roaming in progress. * @QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS: FW rejected the TWT * setup request due to channel switch in progress. * @QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS: FW rejected the TWT setup * request due to scan in progress. * QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE: The driver requested to * terminate an existing TWT session on power save exit request from userspace. * Used on the TWT_TERMINATE notification from the driver/firmware. */ enum qca_wlan_vendor_twt_status { QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED = 1, QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID = 2, QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY = 3, QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST = 4, QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED = 5, QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM = 6, QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY = 7, QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE = 8, QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK = 9, QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10, QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11, QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12, QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13, QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID = 14, QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15, QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16, QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17, QCA_WLAN_VENDOR_TWT_STATUS_SCC_MCC_CONCURRENCY_TERMINATE = 18, QCA_WLAN_VENDOR_TWT_STATUS_ROAMING_IN_PROGRESS = 19, QCA_WLAN_VENDOR_TWT_STATUS_CHANNEL_SWITCH_IN_PROGRESS = 20, QCA_WLAN_VENDOR_TWT_STATUS_SCAN_IN_PROGRESS = 21, QCA_WLAN_VENDOR_TWT_STATUS_POWER_SAVE_EXIT_TERMINATE = 22, }; /** * enum qca_wlan_vendor_attr_twt_resume - Represents attributes for * TWT (Target Wake Time) resume request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8) * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT: Optional (u32) * These attributes are used as the SP offset which is the offset from TSF after * which the wake happens. The units are in microseconds. Please note that * _NEXT_TWT is limited to u8 whereas _NEXT2_TWT takes the u32 data. * _NEXT2_TWT takes the precedence over _NEXT_TWT and thus the recommendation * is to use _NEXT2_TWT. If neither of these attributes is provided, the value * will be set to zero. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32) * This attribute represents the next TWT subfield size. * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits, * and 4 for 64 bits. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8). * Flow ID is the unique identifier for each TWT session. This attribute * represents the respective TWT session to resume. * Flow ID values from 0 to 254 represent a single TWT session * Flow ID value of 255 represents all TWT sessions. * If an invalid dialog id is provided, status * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address * Represents the MAC address of the peer to which TWT Resume is * being sent. This is used in AP mode to represent the respective * client and is a required parameter. In STA mode, this is an optional * parameter */ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID = 3, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT = 4, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAX = QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_twt_nudge - Represents attributes for * TWT (Target Wake Time) nudge request. TWT nudge is a combination of suspend * and resume in a single request. These attributes are sent as part of * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8) * Flow ID is the unique identifier for each TWT session. This attribute * represents the respective TWT session to suspend and resume. * Flow ID values from 0 to 254 represent a single TWT session * Flow ID value of 255 represents all TWT sessions in TWT NUDGE request * and response. * If an invalid dialog id is provided, status * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32) * This attribute is used as the SP offset which is the offset from * TSF after which the wake happens. The units are in microseconds. * * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE: Required (u32) * This attribute represents the next TWT subfield size. * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits, * and 4 for 64 bits. * * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR: 6-byte MAC address * Represents the MAC address of the peer to which TWT Suspend and Resume is * being sent. This is used in AP mode to represent the respective * client and is a required parameter. In STA mode, this is an optional * parameter. * * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF: Optional (u64) * This field contains absolute TSF value of the time at which the TWT * session will be resumed. */ enum qca_wlan_vendor_attr_twt_nudge { QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID = 1, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX = QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_twt_stats: Represents attributes for * TWT (Target Wake Time) get statistics and clear statistics request. * These attributes are sent as part of * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID: Required (u8) * Flow ID is the unique identifier for each TWT session. This attribute * represents the respective TWT session for get and clear TWT statistics. * Flow ID values from 0 to 254 represent a single TWT session * Flow ID value of 255 represents all TWT sessions in * 1) TWT GET STATISTICS request and response * 2) TWT CLEAR STATISTICS request * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR: 6-byte MAC address * Represents the MAC address of the peer for which TWT Statistics * is required. * In AP mode this is used to represent the respective * client and is a required parameter for * 1) TWT GET STATISTICS request and response * 2) TWT CLEAR STATISTICS request and response * In STA mode, this is an optional parameter. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION: Required (u32) * This is the duration of the service period in microseconds. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION: Required (u32) * Average of the actual wake duration observed so far. Unit is microseconds. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS: Required (u32) * The number of TWT service periods elapsed so far. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION: Required (u32) * This is the minimum value of the wake duration observed across * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is * microseconds. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION: Required (u32) * This is the maximum value of wake duration observed across * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is * microseconds. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU: Required (u32) * Average number of MPDUs transmitted successfully across * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU: Required (u32) * Average number of MPDUs received successfully across * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE: Required (u32) * Average number of bytes transmitted successfully across * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE: Required (u32) * Average number of bytes received successfully across * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. * * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS: Required (u32) * Status of the TWT GET STATISTICS request. * This contains status values in enum qca_wlan_vendor_twt_status * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. */ enum qca_wlan_vendor_attr_twt_stats { QCA_WLAN_VENDOR_ATTR_TWT_STATS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID = 1, QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR = 2, QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION = 3, QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION = 4, QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS = 5, QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION = 6, QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION = 7, QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU = 8, QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU = 9, QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE = 10, QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE = 11, QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS = 12, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX = QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST - 1, }; /** * qca_wlan_twt_get_capa - Represents the bitmap of TWT capabilities * supported by the device and the peer. * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_GET_CAPABILITIES * * @QCA_WLAN_TWT_CAPA_REQUESTOR: TWT requestor support is advertised by * TWT non-scheduling STA. This capability is advertised in the HE * Capability/Extended Capabilities information element in the * Association Request frame by the device. * * @QCA_WLAN_TWT_CAPA_RESPONDER: TWT responder support is advertised by * the TWT scheduling AP. This capability is advertised in the Extended * Capabilities/HE Capabilities information element. * * @QCA_WLAN_TWT_CAPA_BROADCAST: On the requestor side, this indicates support * for the broadcast TWT functionality. On the responder side, this indicates * support for the role of broadcast TWT scheduling functionality. This * capability is advertised in the HE Capabilities information element. * * @QCA_WLAN_TWT_CAPA_TWT_FLEXIBLE: The device supports flexible TWT schedule. * This capability is advertised in the HE Capabilities information element. * * @QCA_WLAN_TWT_CAPA_REQUIRED: The TWT Required is advertised by AP to indicate * that it mandates the associated HE STAs to support TWT. This capability is * advertised by AP in the HE Operation Parameters field of the HE Operation * information element. */ enum qca_wlan_twt_capa { QCA_WLAN_TWT_CAPA_REQUESTOR = BIT(0), QCA_WLAN_TWT_CAPA_RESPONDER = BIT(1), QCA_WLAN_TWT_CAPA_BROADCAST = BIT(2), QCA_WLAN_TWT_CAPA_FLEXIBLE = BIT(3), QCA_WLAN_TWT_CAPA_REQUIRED = BIT(4), }; /** * enum qca_wlan_vendor_attr_twt_capability - Represents attributes for TWT * get capabilities request type. Used by QCA_WLAN_TWT_GET_CAPABILITIES TWT * operation. * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR: 6-byte MAC address * Represents the MAC address of the peer for which the TWT capabilities * are being queried. This is used in AP mode to represent the respective * client. In STA mode, this is an optional parameter. * * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF: (u16). * Self TWT capabilities. Carries a bitmap of TWT capabilities specified in * enum qca_wlan_twt_capa. * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER: (u16). * Peer TWT capabilities. Carries a bitmap of TWT capabilities specified in * enum qca_wlan_twt_capa. */ enum qca_wlan_vendor_attr_twt_capability { QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR = 1, QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF = 2, QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAX = QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_twt_set_param: Represents attributes for * TWT (Target Wake Time) related parameters. It is used when * %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION is set to %QCA_WLAN_TWT_SET_PARAM. * These attributes are sent as part of %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE: Optional (u8) * This attribute configures AC parameters to be used for all TWT * sessions in AP mode. * Uses the enum qca_wlan_ac_type values. */ enum qca_wlan_vendor_attr_twt_set_param { QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AP_AC_VALUE = 1, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_MAX = QCA_WLAN_VENDOR_ATTR_TWT_SET_PARAM_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by * the TWT responder * * @QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE: TWT responder suggests TWT * parameters that are different from TWT requesting STA suggested * or demanded TWT parameters * @QCA_WLAN_VENDOR_TWT_RESP_DICTATE: TWT responder demands TWT * parameters that are different from TWT requesting STA TWT suggested * or demanded parameters * @QCA_WLAN_VENDOR_TWT_RESP_REJECT: TWT responder rejects TWT * setup * @QCA_WLAN_VENDOR_TWT_RESP_ACCEPT: TWT responder accepts the TWT * setup. */ enum qca_wlan_vendor_twt_setup_resp_type { QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE = 1, QCA_WLAN_VENDOR_TWT_RESP_DICTATE = 2, QCA_WLAN_VENDOR_TWT_RESP_REJECT = 3, QCA_WLAN_VENDOR_TWT_RESP_ACCEPT = 4, }; /** * enum qca_wlan_vendor_twt_setup_req_type - Required (u8) * Represents the setup type being requested for TWT. * @QCA_WLAN_VENDOR_TWT_SETUP_REQUEST: STA is not specifying all the TWT * parameters but relying on AP to fill the parameters during the negotiation. * @QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST: STA will provide all the suggested * values which the AP may accept or AP may provide alternative parameters * which the STA may accept. * @QCA_WLAN_VENDOR_TWT_SETUP_DEMAND: STA is not willing to accept any * alternate parameters than the requested ones. */ enum qca_wlan_vendor_twt_setup_req_type { QCA_WLAN_VENDOR_TWT_SETUP_REQUEST = 1, QCA_WLAN_VENDOR_TWT_SETUP_SUGGEST = 2, QCA_WLAN_VENDOR_TWT_SETUP_DEMAND = 3, }; /** * enum qca_wlan_roam_scan_event_type - Type of roam scan event * * Indicates the type of roam scan event sent by firmware/driver. * * @QCA_WLAN_ROAM_SCAN_TRIGGER_EVENT: Roam scan trigger event type. * @QCA_WLAN_ROAM_SCAN_STOP_EVENT: Roam scan stopped event type. */ enum qca_wlan_roam_scan_event_type { QCA_WLAN_ROAM_SCAN_TRIGGER_EVENT = 0, QCA_WLAN_ROAM_SCAN_STOP_EVENT = 1, }; /** * enum qca_wlan_roam_scan_trigger_reason - Roam scan trigger reason * * Indicates the reason for triggering roam scan by firmware/driver. * * @QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_LOW_RSSI: Due to low RSSI of current AP. * @QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_HIGH_PER: Due to high packet error rate. */ enum qca_wlan_roam_scan_trigger_reason { QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_LOW_RSSI = 0, QCA_WLAN_ROAM_SCAN_TRIGGER_REASON_HIGH_PER = 1, }; /** * enum qca_wlan_vendor_attr_roam_scan - Vendor subcmd attributes to report * roam scan related details from driver/firmware to user space. enum values * are used for NL attributes sent with * %QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT sub command. */ enum qca_wlan_vendor_attr_roam_scan { QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_INVALID = 0, /* Encapsulates type of roam scan event being reported. enum * qca_wlan_roam_scan_event_type describes the possible range of * values. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_EVENT_TYPE = 1, /* Encapsulates reason for triggering roam scan. enum * qca_wlan_roam_scan_trigger_reason describes the possible range of * values. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_TRIGGER_REASON = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_MAX = QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_cfr_data_transport_modes - Defines QCA vendor CFR data * transport modes and is used by the attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE as a part of the vendor * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. * @QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS: Use relayfs to send CFR data. * @QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS: Use netlink events to send CFR * data. The data shall be encapsulated within * QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA along with the vendor sub command * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an asynchronous event. */ enum qca_wlan_vendor_cfr_data_transport_modes { QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS = 0, QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS = 1, }; /** * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. * @QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL: CFR method using QoS Null frame * @QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE: CFR method using QoS Null frame * with phase * @QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE: CFR method using Probe Response frame */ enum qca_wlan_vendor_cfr_method { QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0, QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE = 1, QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE = 2, }; /** * enum qca_wlan_vendor_cfr_capture_type - QCA vendor CFR capture type used by * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE. * @QCA_WLAN_VENDOR_CFR_DIRECT_FTM: Filter directed FTM ACK frames. * @QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK: Filter all FTM ACK frames. * @QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP: Filter NDPA NDP directed frames. * @QCA_WLAN_VENDOR_CFR_TA_RA: Filter frames based on TA/RA/Subtype which * is provided by one or more of below attributes: * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER * @QCA_WLAN_CFR_ALL_PACKET: Filter all packets. * @QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL: Filter all NDPA NDP frames. */ enum qca_wlan_vendor_cfr_capture_type { QCA_WLAN_VENDOR_CFR_DIRECT_FTM = 0, QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK = 1, QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP = 2, QCA_WLAN_VENDOR_CFR_TA_RA = 3, QCA_WLAN_VENDOR_CFR_ALL_PACKET = 4, QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL = 5, }; /** * enum qca_wlan_vendor_peer_cfr_capture_attr - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer * Channel Frequency Response capture parameters and enable periodic CFR * capture. * * @QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR: Optional (6-byte MAC address) * MAC address of peer. This is for CFR version 1 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE: Required (flag) * Enable peer CFR capture. This attribute is mandatory to enable peer CFR * capture. If this attribute is not present, peer CFR capture is disabled. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH: Optional (u8) * BW of measurement, attribute uses the values in enum nl80211_chan_width * Supported values: 20, 40, 80, 80+80, 160. * Note that all targets may not support all bandwidths. * This attribute is mandatory for version 1 if attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY: Optional (u32) * Periodicity of CFR measurement in milliseconds. * Periodicity should be a multiple of Base timer. * Current Base timer value supported is 10 milliseconds (default). * 0 for one shot capture. * This attribute is mandatory for version 1 if attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD: Optional (u8) * Method used to capture Channel Frequency Response. * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. * This attribute is mandatory for version 1 if attribute * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. * * @QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE: Optional (flag) * Enable periodic CFR capture. * This attribute is mandatory for version 1 to enable Periodic CFR capture. * If this attribute is not present, periodic CFR capture is disabled. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION: Optional (u8) * Value is 1 or 2 since there are two versions of CFR capture. Two versions * can't be enabled at same time. This attribute is mandatory if target * support both versions and use one of them. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP: Optional (u32) * This attribute is mandatory for version 2 if * QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY is used. * Bits 15:0 bitfield indicates which group is to be enabled. * Bits 31:16 Reserved for future use. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION: Optional (u32) * CFR capture duration in microsecond. This attribute is mandatory for * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL is used. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL: Optional (u32) * CFR capture interval in microsecond. This attribute is mandatory for * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION is used. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE: Optional (u32) * CFR capture type is defined in enum qca_wlan_vendor_cfr_capture_type. * This attribute is mandatory for version 2. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK: Optional (u64) * Bitfield indicating which user in the current UL MU transmissions are * enabled for CFR capture. Bits 36 to 0 indicate user indexes for 37 users in * a UL MU transmission. If bit 0 is set, the CFR capture will happen for user * index 0 in the current UL MU transmission. If bits 0 and 2 are set, CFR * capture for UL MU TX corresponds to user indices 0 and 2. Bits 63:37 are * reserved for future use. This is for CFR version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT: Optional (u32) * Indicates the number of consecutive RX frames to be skipped before CFR * capture is enabled again. This is for CFR version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE: Nested attribute containing * one or more %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY attributes. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY: Nested attribute containing * the following group attributes: * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER, * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER: Optional (u32) * Target supports multiple groups for some configurations. The group number * can be any value between 0 and 15. This is for CFR version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA: Optional (6-byte MAC address) * Transmitter address which is used to filter frames. This MAC address takes * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK. This is for CFR * version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA: Optional (6-byte MAC address) * Receiver address which is used to filter frames. This MAC address takes * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK. This is for CFR * version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK: Optional (6-byte MAC address) * Mask of transmitter address which is used to filter frames. This is for CFR * version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK: Optional (6-byte MAC address) * Mask of receiver address which is used to filter frames. This is for CFR * version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS: Optional (u32) * Indicates frames with a specific NSS will be filtered for CFR capture. * This is for CFR version 2 only. This is a bitmask. Bits 7:0 request CFR * capture to be done for frames matching the NSS specified within this bitmask. * Bits 31:8 are reserved for future use. Bits 7:0 map to NSS: * bit 0 : NSS 1 * bit 1 : NSS 2 * ... * bit 7 : NSS 8 * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW: Optional (u32) * Indicates frames with a specific bandwidth will be filtered for CFR capture. * This is for CFR version 2 only. This is a bitmask. Bits 4:0 request CFR * capture to be done for frames matching the bandwidths specified within this * bitmask. Bits 31:5 are reserved for future use. Bits 4:0 map to bandwidth * numerated in enum nl80211_band (although not all bands may be supported * by a given device). * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER: Optional (u32) * Management frames matching the subtype filter categories will be filtered in * by MAC for CFR capture. This is a bitmask in which each bit represents the * corresponding Management frame subtype value per IEEE Std 802.11-2016, * 9.2.4.1.3 Type and Subtype subfields. For example, Beacon frame control type * is 8 and its value is 1 << 8 = 0x100. This is for CFR version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER: Optional (u32) * Control frames matching the subtype filter categories will be filtered in by * MAC for CFR capture. This is a bitmask in which each bit represents the * corresponding Control frame subtype value per IEEE Std 802.11-2016, * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER: Optional (u32) * Data frames matching the subtype filter categories will be filtered in by * MAC for CFR capture. This is a bitmask in which each bit represents the * corresponding Data frame subtype value per IEEE Std 802.11-2016, * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE: Optional (u8) * Userspace can use this attribute to specify the driver about which transport * mode shall be used by the driver to send CFR data to userspace. Uses values * from enum qca_wlan_vendor_cfr_data_transport_modes. When this attribute is * not present, the driver shall use the default transport mechanism which is * QCA_WLAN_VENDOR_CFR_DATA_RELAY_FS. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID: Optional (u32) * Userspace can use this attribute to specify the nl port id of the application * which receives the CFR data and processes it further so that the drivers can * unicast the netlink events to a specific application. Optionally included * when QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE is set to * QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS, not required otherwise. The drivers * shall multicast the netlink events when this attribute is not included. * * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA: Required (NLA_BINARY). * This attribute will be used by the driver to encapsulate and send CFR data * to userspace along with QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG as an * asynchronous event when the driver is configured to send CFR data using * netlink events with %QCA_WLAN_VENDOR_CFR_DATA_NETLINK_EVENTS. */ enum qca_wlan_vendor_peer_cfr_capture_attr { QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0, QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1, QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2, QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3, QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4, QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5, QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6, QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION = 7, QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP = 8, QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION = 9, QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL = 10, QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE = 11, QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK = 12, QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT = 13, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE = 14, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY = 15, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER = 16, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA = 17, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA = 18, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK = 19, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK = 20, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS = 21, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW = 22, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24, QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25, QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_TRANSPORT_MODE = 26, QCA_WLAN_VENDOR_ATTR_PEER_CFR_DATA_RECEIVER_PID = 27, QCA_WLAN_VENDOR_ATTR_PEER_CFR_RESP_DATA = 28, /* Keep last */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX = QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST - 1, }; /** * enum qca_wlan_throughput_level - Current throughput level * * Indicates the current level of throughput calculated by the driver. The * driver may choose different thresholds to decide whether the throughput level * is low or medium or high based on variety of parameters like physical link * capacity of the current connection, the number of packets being dispatched * per second, etc. The throughput level events might not be consistent with the * actual current throughput value being observed. * * @QCA_WLAN_THROUGHPUT_LEVEL_LOW: Low level of throughput * @QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM: Medium level of throughput * @QCA_WLAN_THROUGHPUT_LEVEL_HIGH: High level of throughput */ enum qca_wlan_throughput_level { QCA_WLAN_THROUGHPUT_LEVEL_LOW = 0, QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM = 1, QCA_WLAN_THROUGHPUT_LEVEL_HIGH = 2, }; /** * enum qca_wlan_vendor_attr_throughput_change - Vendor subcmd attributes to * report throughput changes from the driver to user space. enum values are used * for netlink attributes sent with * %QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT sub command. */ enum qca_wlan_vendor_attr_throughput_change { QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_INVALID = 0, /* Indicates the direction of throughput in which the change is being * reported. u8 attribute. Value is 0 for TX and 1 for RX. */ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION = 1, /* Indicates the newly observed throughput level. enum * qca_wlan_throughput_level describes the possible range of values. * u8 attribute. */ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL = 2, /* Indicates the driver's guidance on the new value to be set to * kernel's TCP parameter tcp_limit_output_bytes. u32 attribute. The * driver may optionally include this attribute. */ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES = 3, /* Indicates the driver's guidance on the new value to be set to * kernel's TCP parameter tcp_adv_win_scale. s8 attribute. Possible * values are from -31 to 31. The driver may optionally include this * attribute. */ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE = 4, /* Indicates the driver's guidance on the new value to be set to * kernel's TCP parameter tcp_delack_seg. u32 attribute. The driver may * optionally include this attribute. */ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_MAX = QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST - 1, }; /** * enum qca_coex_config_profiles - This enum defines different types of * traffic streams that can be prioritized one over the other during coex * scenarios. * The types defined in this enum are categorized in the below manner. * 0 - 31 values corresponds to WLAN * 32 - 63 values corresponds to BT * 64 - 95 values corresponds to Zigbee * @QCA_WIFI_STA_DISCOVERY: Prioritize discovery frames for WLAN STA * @QCA_WIFI_STA_CONNECTION: Prioritize connection frames for WLAN STA * @QCA_WIFI_STA_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN STA * @QCA_WIFI_STA_DATA : Prioritize data frames for WLAN STA * @QCA_WIFI_STA_ALL: Priritize all frames for WLAN STA * @QCA_WIFI_SAP_DISCOVERY: Prioritize discovery frames for WLAN SAP * @QCA_WIFI_SAP_CONNECTION: Prioritize connection frames for WLAN SAP * @QCA_WIFI_SAP_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN SAP * @QCA_WIFI_SAP_DATA: Prioritize data frames for WLAN SAP * @QCA_WIFI_SAP_ALL: Prioritize all frames for WLAN SAP * @QCA_BT_A2DP: Prioritize BT A2DP * @QCA_BT_BLE: Prioritize BT BLE * @QCA_BT_SCO: Prioritize BT SCO * @QCA_ZB_LOW: Prioritize Zigbee Low * @QCA_ZB_HIGH: Prioritize Zigbee High */ enum qca_coex_config_profiles { /* 0 - 31 corresponds to WLAN */ QCA_WIFI_STA_DISCOVERY = 0, QCA_WIFI_STA_CONNECTION = 1, QCA_WIFI_STA_CLASS_3_MGMT = 2, QCA_WIFI_STA_DATA = 3, QCA_WIFI_STA_ALL = 4, QCA_WIFI_SAP_DISCOVERY = 5, QCA_WIFI_SAP_CONNECTION = 6, QCA_WIFI_SAP_CLASS_3_MGMT = 7, QCA_WIFI_SAP_DATA = 8, QCA_WIFI_SAP_ALL = 9, QCA_WIFI_CASE_MAX = 31, /* 32 - 63 corresponds to BT */ QCA_BT_A2DP = 32, QCA_BT_BLE = 33, QCA_BT_SCO = 34, QCA_BT_CASE_MAX = 63, /* 64 - 95 corresponds to Zigbee */ QCA_ZB_LOW = 64, QCA_ZB_HIGH = 65, QCA_ZB_CASE_MAX = 95, /* 0xff is default value if the u8 profile value is not set. */ QCA_COEX_CONFIG_PROFILE_DEFAULT_VALUE = 255 }; /** * enum qca_vendor_attr_coex_config_types - Coex configurations types. * This enum defines the valid set of values of coex configuration types. These * values may used by attribute * %QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE. * * @QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET: Reset all the * weights to default values. * @QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START: Start to config * weights with configurability value. */ enum qca_vendor_attr_coex_config_types { QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_INVALID = 0, QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_RESET = 1, QCA_WLAN_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_COEX_START = 2, }; /** * enum qca_vendor_attr_coex_config - Specifies vendor coex config attributes * * @QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES: This attribute contains variable * length array of 8-bit values from enum qca_coex_config_profiles. * FW will prioritize the profiles in the order given in the array encapsulated * in this attribute. * For example: * ----------------------------------------------------------------------- * | 1 | 34 | 32 | 65 | * ----------------------------------------------------------------------- * If the attribute contains the values defined in above array then it means * 1) Wifi STA connection has priority over BT_SCO, BT_A2DP and ZIGBEE HIGH. * 2) BT_SCO has priority over BT_A2DP. * 3) BT_A2DP has priority over ZIGBEE HIGH. * Profiles which are not listed in this array shall not be preferred over the * profiles which are listed in the array as a part of this attribute. */ enum qca_vendor_attr_coex_config { QCA_VENDOR_ATTR_COEX_CONFIG_INVALID = 0, QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES = 1, /* Keep last */ QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST, QCA_VENDOR_ATTR_COEX_CONFIG_MAX = QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST - 1, }; /** * enum qca_vendor_attr_coex_config_three_way - Specifies vendor coex config * attributes * Attributes for data used by QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG * * QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE: u32 attribute. * Indicate config type. * The config types are 32-bit values from qca_vendor_attr_coex_config_types * * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1: u32 attribute. * Indicate the Priority 1 profiles. * The profiles are 8-bit values from enum qca_coex_config_profiles. * In same priority level, maximum to 4 profiles can be set here. * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2: u32 attribute. * Indicate the Priority 2 profiles. * The profiles are 8-bit values from enum qca_coex_config_profiles. * In same priority level, maximum to 4 profiles can be set here. * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3: u32 attribute. * Indicate the Priority 3 profiles. * The profiles are 8-bit values from enum qca_coex_config_profiles. * In same priority level, maximum to 4 profiles can be set here. * @QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4: u32 attribute. * Indicate the Priority 4 profiles. * The profiles are 8-bit values from enum qca_coex_config_profiles. * In same priority level, maximum to 4 profiles can be set here. * NOTE: * Limitations for QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_x priority * arrangement: * 1: In the same u32 attribute (priority x), the profiles enum values own * same priority level. * 2: 0xff is default value if the u8 profile value is not set. * 3: max to 4 rules/profiles in same priority level. * 4: max to 4 priority level (priority 1 - priority 4) * 5: one priority level only supports one scenario from WLAN/BT/ZB, * hybrid rules not support. * 6: if WMI_COEX_CONFIG_THREE_WAY_COEX_RESET called, priority x will * remain blank to reset all parameters. * For example: * * If the attributes as follow: * priority 1: * ------------------------------------ * | 0xff | 0 | 1 | 2 | * ------------------------------------ * priority 2: * ------------------------------------- * | 0xff | 0xff | 0xff | 32 | * ------------------------------------- * priority 3: * ------------------------------------- * | 0xff | 0xff | 0xff | 65 | * ------------------------------------- * then it means: * 1: WIFI_STA_DISCOVERY, WIFI_STA_CLASS_3_MGMT and WIFI_STA_CONNECTION * owns same priority level. * 2: WIFI_STA_DISCOVERY, WIFI_STA_CLASS_3_MGMT and WIFI_STA_CONNECTION * has priority over BT_A2DP and ZB_HIGH. * 3: BT_A2DP has priority over ZB_HIGH. */ enum qca_vendor_attr_coex_config_three_way { QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_INVALID = 0, QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_CONFIG_TYPE = 1, QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_1 = 2, QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_2 = 3, QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_3 = 4, QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_PRIORITY_4 = 5, /* Keep last */ QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_AFTER_LAST, QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_MAX = QCA_VENDOR_ATTR_COEX_CONFIG_THREE_WAY_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_link_properties - Represent the link properties. * * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR: MAC address of the peer * (STA/AP) for the connected link. * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS: Attribute containing a * &struct nl80211_sta_flag_update for the respective connected link. MAC * address of the peer represented by * QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR. */ enum qca_wlan_vendor_attr_link_properties { QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID = 0, /* 1 - 3 are reserved */ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR = 4, QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS = 5, /* Keep last */ QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST, QCA_VENDOR_ATTR_LINK_PROPERTIES_MAX = QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST - 1, }; /** * enum qca_vendor_attr_peer_stats_cache_type - Represents peer stats cache type * This enum defines the valid set of values of peer stats cache types. These * values are used by attribute * %QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE. * * @QCA_WLAN_VENDOR_ATTR_PEER_TX_RATE_STATS: Represents peer TX rate statistics * @QCA_WLAN_VENDOR_ATTR_PEER_RX_RATE_STATS: Represents peer RX rate statistics * @QCA_WLAN_VENDOR_ATTR_PEER_TX_SOJOURN_STATS: Represents peer TX sojourn * statistics */ enum qca_vendor_attr_peer_stats_cache_type { QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE_INVALID = 0, QCA_WLAN_VENDOR_ATTR_PEER_TX_RATE_STATS, QCA_WLAN_VENDOR_ATTR_PEER_RX_RATE_STATS, QCA_WLAN_VENDOR_ATTR_PEER_TX_SOJOURN_STATS, }; /** * enum qca_wlan_vendor_attr_peer_stats_cache_params - This enum defines * attributes required for QCA_NL80211_VENDOR_SUBCMD_PEER_STATS_CACHE_FLUSH * Information in these attributes is used to flush peer rate statistics from * the driver to user application. * * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE: Unsigned 32-bit attribute * Indicate peer statistics cache type. * The statistics types are 32-bit values from * enum qca_vendor_attr_peer_stats_cache_type. * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC: Unsigned 8-bit array * of size 6 octets, representing the peer MAC address. * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA: Opaque data attribute * containing buffer of statistics to send to application layer entity. * @QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE: Unsigned 64-bit attribute * representing a cookie for peer unique session. */ enum qca_wlan_vendor_attr_peer_stats_cache_params { QCA_WLAN_VENDOR_ATTR_PEER_STATS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_TYPE = 1, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_MAC = 2, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_DATA = 3, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_PEER_COOKIE = 4, /* Keep last */ QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_LAST, QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_MAX = QCA_WLAN_VENDOR_ATTR_PEER_STATS_CACHE_LAST - 1 }; /** * enum qca_mpta_helper_attr_zigbee_state - Current Zigbee state * This enum defines all the possible states of Zigbee, which can be * delivered in the QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE attribute. * * @ZIGBEE_IDLE: Zigbee in idle state * @ZIGBEE_FORM_NETWORK: Zigbee forming network * @ZIGBEE_WAIT_JOIN: Zigbee waiting for joining network * @ZIGBEE_JOIN: Zigbee joining network * @ZIGBEE_NETWORK_UP: Zigbee network is up * @ZIGBEE_HMI: Zigbee in HMI mode */ enum qca_mpta_helper_attr_zigbee_state { ZIGBEE_IDLE = 0, ZIGBEE_FORM_NETWORK = 1, ZIGBEE_WAIT_JOIN = 2, ZIGBEE_JOIN = 3, ZIGBEE_NETWORK_UP = 4, ZIGBEE_HMI = 5, }; /* * enum qca_mpta_helper_vendor_attr - Attributes used in vendor sub-command * QCA_NL80211_VENDOR_SUBCMD_MPTA_HELPER_CONFIG. */ enum qca_mpta_helper_vendor_attr { QCA_MPTA_HELPER_VENDOR_ATTR_INVALID = 0, /* Optional attribute used to update Zigbee state. * enum qca_mpta_helper_attr_zigbee_state. * NLA_U32 attribute. */ QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE = 1, /* Optional attribute used to configure WLAN duration for Shape-OCS * during interrupt. * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION. * Value range 0 ~ 300 (ms). * NLA_U32 attribute. */ QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION = 2, /* Optional attribute used to configure non-WLAN duration for Shape-OCS * during interrupt. * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION. * Value range 0 ~ 300 (ms). * NLA_U32 attribute. */ QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION = 3, /* Optional attribute used to configure WLAN duration for Shape-OCS * monitor period. * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION. * Value range 0 ~ 300 (ms) * NLA_U32 attribute */ QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION = 4, /* Optional attribute used to configure non-WLAN duration for Shape-OCS * monitor period. * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION. * Value range 0 ~ 300 (ms) * NLA_U32 attribute */ QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION = 5, /* Optional attribute used to configure OCS interrupt duration. * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION. * Value range 1000 ~ 20000 (ms) * NLA_U32 attribute */ QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION = 6, /* Optional attribute used to configure OCS monitor duration. * Set in pair with QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION. * Value range 1000 ~ 20000 (ms) * NLA_U32 attribute */ QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION = 7, /* Optional attribute used to notify WLAN firmware the current Zigbee * channel. * Value range 11 ~ 26 * NLA_U32 attribute */ QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_CHAN = 8, /* Optional attribute used to configure WLAN mute duration. * Value range 0 ~ 400 (ms) * NLA_U32 attribute */ QCA_MPTA_HELPER_VENDOR_ATTR_WLAN_MUTE_DURATION = 9, /* keep last */ QCA_MPTA_HELPER_VENDOR_ATTR_AFTER_LAST, QCA_MPTA_HELPER_VENDOR_ATTR_MAX = QCA_MPTA_HELPER_VENDOR_ATTR_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_beacon_reporting_op_types - Defines different types of * operations for which %QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING can be used. * Will be used by %QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE. * * @QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START: Sent by userspace to the driver * to request the driver to start reporting Beacon frames. * @QCA_WLAN_VENDOR_BEACON_REPORTING_OP_STOP: Sent by userspace to the driver to * request the driver to stop reporting Beacon frames. * @QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO: Sent by the driver to * userspace to report received Beacon frames. * @QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE: Sent by the driver to userspace * to indicate that the driver is going to pause reporting Beacon frames. */ enum qca_wlan_vendor_beacon_reporting_op_types { QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START = 0, QCA_WLAN_VENDOR_BEACON_REPORTING_OP_STOP = 1, QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO = 2, QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE = 3, }; /** * enum qca_wlan_vendor_beacon_reporting_pause_reasons - Defines different types * of reasons for which the driver is pausing reporting Beacon frames. Will be * used by %QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON. * * @QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_UNSPECIFIED: For unspecified * reasons. * @QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_SCAN_STARTED: When the * driver/firmware is starting a scan. * @QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_DISCONNECTED: When the * driver/firmware disconnects from the ESS and indicates the disconnection to * userspace (non-seamless roaming case). This reason code will be used by the * driver/firmware to indicate stopping of beacon report events. Userspace will * need to start beacon reporting again (if desired) by sending vendor command * QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING with * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START after the next connection is * completed. */ enum qca_wlan_vendor_beacon_reporting_pause_reasons { QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_UNSPECIFIED = 0, QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_SCAN_STARTED = 1, QCA_WLAN_VENDOR_BEACON_REPORTING_PAUSE_REASON_DISCONNECTED = 2, }; /* * enum qca_wlan_vendor_attr_beacon_reporting_params - List of attributes used * in vendor sub-command QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING. */ enum qca_wlan_vendor_attr_beacon_reporting_params { QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_INVALID = 0, /* Specifies the type of operation that the vendor command/event is * intended for. Possible values for this attribute are defined in * enum qca_wlan_vendor_beacon_reporting_op_types. u32 attribute. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE = 1, /* Optionally set by userspace to request the driver to report Beacon * frames using asynchronous vendor events when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START. NLA_FLAG attribute. * If this flag is not set, the driver will only update Beacon frames in * cfg80211 scan cache but not send any vendor events. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING = 2, /* Optionally used by userspace to request the driver/firmware to report * Beacon frames periodically when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START. * u32 attribute, indicates the period of Beacon frames to be reported * and in the units of beacon interval. * If this attribute is missing in the command, then the default value * of 1 will be assumed by driver, i.e., to report every Beacon frame. * Zero is an invalid value. * If a valid value is received for this attribute, the driver will * update the cfg80211 scan cache periodically as per the value received * in this attribute in addition to updating the cfg80211 scan cache * when there is significant change in Beacon frame IEs. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD = 3, /* Used by the driver to encapsulate the SSID when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. * u8 array with a maximum size of 32. * * When generating beacon report from non-MBSSID Beacon frame, the SSID * will be taken from the SSID element of the received Beacon frame. * * When generating beacon report from Multiple BSSID Beacon frame and if * the BSSID of the current connected BSS matches the BSSID of the * transmitting BSS, the SSID will be taken from the SSID element of the * received Beacon frame. * * When generating beacon report from Multiple BSSID Beacon frame and if * the BSSID of the current connected BSS matches the BSSID of one of * the* nontransmitting BSSs, the SSID will be taken from the SSID field * included in the nontransmitted BSS profile whose derived BSSID is * same as the BSSID of the current connected BSS. When there is no * nontransmitted BSS profile whose derived BSSID is same as the BSSID * of current connected* BSS, this attribute will not be present. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_SSID = 4, /* Used by the driver to encapsulate the BSSID of the AP to which STA is * currently connected to when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. u8 array with a * fixed size of 6 bytes. * * When generating beacon report from a Multiple BSSID beacon and the * current connected BSSID matches one of the nontransmitted BSSIDs in a * Multiple BSSID set, this BSSID will be that particular nontransmitted * BSSID and not the transmitted BSSID (i.e., the transmitting address * of the Beacon frame). */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BSSID = 5, /* Used by the driver to encapsulate the frequency in MHz on which * the Beacon frame was received when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is * set to QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. * u32 attribute. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_FREQ = 6, /* Used by the driver to encapsulate the Beacon interval * when the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. * u16 attribute. The value will be copied from the Beacon frame and the * units are TUs. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BI = 7, /* Used by the driver to encapsulate the Timestamp field from the Beacon * frame when the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set * to QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. * u64 attribute. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_TSF = 8, /* Used by the driver to encapsulate the CLOCK_BOOTTIME when this * Beacon frame is received in the driver when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. u64 attribute, in * the units of nanoseconds. This value is expected to have accuracy of * about 10 ms. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_BOOTTIME_WHEN_RECEIVED = 9, /* Used by the driver to encapsulate the IEs of the Beacon frame from * which this event is generated when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_BEACON_INFO. u8 array. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_IES = 10, /* Used by the driver to specify the reason for the driver/firmware to * pause sending beacons to userspace when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE. Possible values are * defined in enum qca_wlan_vendor_beacon_reporting_pause_reasons, u32 * attribute. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PAUSE_REASON = 11, /* Used by the driver to specify whether the driver will automatically * resume reporting beacon events to userspace later (for example after * the ongoing off-channel activity is completed etc.) when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE. NLA_FLAG attribute. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES = 12, /* Optionally set by userspace to request the driver not to resume * beacon reporting after a pause is completed, when the * QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE is set to * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START. NLA_FLAG attribute. * If this flag is set, the driver will not resume beacon reporting * after any pause in beacon reporting is completed. Userspace has to * send QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command again in order * to initiate beacon reporting again. If this flag is set in the recent * QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START command, then in the * subsequent QCA_WLAN_VENDOR_BEACON_REPORTING_OP_PAUSE event (if any) * the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be * set by the driver. Setting this flag until and unless there is a * specific need is not recommended as there is a chance of some beacons * received after pause command and next start command being not * reported. */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_DO_NOT_RESUME = 13, /* Keep last */ QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_LAST, QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX = QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_LAST - 1 }; /** * enum qca_vendor_interop_issues_ap_type - Interop issue types * This enum defines the valid set of values of interop issue types. These * values are used by attribute %QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_TYPE. * * @QCA_VENDOR_INTEROP_ISSUES_AP_ON_STA_PS: The AP has power save interop issue * when the STA's Qpower feature is enabled. */ enum qca_vendor_interop_issues_ap_type { QCA_VENDOR_INTEROP_ISSUES_AP_INVALID = 0, QCA_VENDOR_INTEROP_ISSUES_AP_ON_STA_PS = 1, }; /** * enum qca_vendor_attr_interop_issues_ap - attribute for AP with interop issues * Values are used by %QCA_NL80211_VENDOR_SUBCMD_INTEROP_ISSUES_AP. * * @QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_INVALID: Invalid value * @QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_TYPE: Interop issue type * 32-bit unsigned value. The values defined in enum * qca_vendor_interop_issues_ap_type are used. * @QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_LIST: APs' BSSID container * array of nested QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_BSSID attributes. * It is present and mandatory for the command but is not used for the event * since only a single BSSID is reported in an event. * @QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_BSSID: AP's BSSID 6-byte MAC address. * It is used within the nested QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_LIST * attribute in command case and without such encapsulation in the event case. * @QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_AFTER_LAST: last value * @QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_MAX: max value */ enum qca_vendor_attr_interop_issues_ap { QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_INVALID, QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_TYPE, QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_LIST, QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_BSSID, /* keep last */ QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_MAX = QCA_WLAN_VENDOR_ATTR_INTEROP_ISSUES_AP_AFTER_LAST - 1 }; /** * enum qca_vendor_oem_device_type - Represents the target device in firmware. * It is used by QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO. * * @QCA_VENDOR_OEM_DEVICE_VIRTUAL: The command is intended for * a virtual device. * * @QCA_VENDOR_OEM_DEVICE_PHYSICAL: The command is intended for * a physical device. */ enum qca_vendor_oem_device_type { QCA_VENDOR_OEM_DEVICE_VIRTUAL = 0, QCA_VENDOR_OEM_DEVICE_PHYSICAL = 1, }; /** * enum qca_wlan_vendor_attr_oem_data_params - Used by the vendor command/event * QCA_NL80211_VENDOR_SUBCMD_OEM_DATA. * * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: This NLA_BINARY attribute is * used to set/query the data to/from the firmware. On query, the same * attribute is used to carry the respective data in the reply sent by the * driver to userspace. The request to set/query the data and the format of the * respective data from the firmware are embedded in the attribute. The * maximum size of the attribute payload is 1024 bytes. * Userspace has to set the QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED * attribute when the data is queried from the firmware. * * @QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO: The binary blob will be routed * based on this field. This optional attribute is included to specify whether * the device type is a virtual device or a physical device for the * command/event. This attribute can be omitted for a virtual device (default) * command/event. * This u8 attribute is used to carry information for the device type using * values defined by enum qca_vendor_oem_device_type. * * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED: This NLA_FLAG attribute * is set when the userspace queries data from the firmware. This attribute * should not be set when userspace sets the OEM data to the firmware. */ enum qca_wlan_vendor_attr_oem_data_params { QCA_WLAN_VENDOR_ATTR_OEM_DATA_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA = 1, QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO = 2, QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX = QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_AFTER_LAST - 1 }; /** * enum qca_wlan_vendor_attr_avoid_frequency_ext - Defines attributes to be * used with vendor command/event QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_EXT. * * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE: Required * Nested attribute containing multiple ranges with following attributes: * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START, * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END, and * QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM. * * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START: Required (u32) * Starting center frequency in MHz. * * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END: Required (u32) * Ending center frequency in MHz. * * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM: * s32 attribute, optional. It is a per frequency range attribute. * The maximum TX power limit from user space is to be applied on an * unrestricted interface for corresponding frequency range. It is also * possible that the actual TX power may be even lower than this cap due to * other considerations such as regulatory compliance, SAR, etc. In absence of * this attribute the driver shall follow current behavior which means * interface (SAP/P2P) function can keep operating on an unsafe channel with TX * power derived by the driver based on regulatory/SAR during interface up. * * @QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK: * u32 attribute, optional. Indicates all the interface types which are * restricted for all frequency ranges provided in * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START and * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END. * This attribute encapsulates bitmasks of interface types defined in * enum nl80211_iftype. If an interface is marked as restricted the driver must * move to a safe channel and if no safe channel is available the driver shall * terminate that interface functionality. In absence of this attribute, * interface (SAP/P2P) can still continue operating on an unsafe channel with * TX power limit derived from either * %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM or based on * regulatory/SAE limits if %QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM * is not provided. */ enum qca_wlan_vendor_attr_avoid_frequency_ext { QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_INVALID = 0, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_RANGE = 1, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_START = 2, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_END = 3, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_POWER_CAP_DBM = 4, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_IFACES_BITMASK = 5, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_MAX = QCA_WLAN_VENDOR_ATTR_AVOID_FREQUENCY_AFTER_LAST - 1 }; /* * enum qca_wlan_vendor_attr_add_sta_node_params - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE. */ enum qca_wlan_vendor_attr_add_sta_node_params { QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_INVALID = 0, /* 6 byte MAC address of STA */ QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_MAC_ADDR = 1, /* Authentication algorithm used by the station of size u16; * defined in enum nl80211_auth_type. */ QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_AUTH_ALGO = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_MAX = QCA_WLAN_VENDOR_ATTR_ADD_STA_NODE_PARAM_AFTER_LAST - 1 }; /** * enum qca_btc_chain_mode - Specifies BT coex chain mode. * This enum defines the valid set of values of BT coex chain mode. * These values are used by attribute %QCA_VENDOR_ATTR_BTC_CHAIN_MODE of * %QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE. * * @QCA_BTC_CHAIN_SHARED: chains of BT and WLAN 2.4G are shared. * @QCA_BTC_CHAIN_SEPARATED: chains of BT and WLAN 2.4G are separated. */ enum qca_btc_chain_mode { QCA_BTC_CHAIN_SHARED = 0, QCA_BTC_CHAIN_SEPARATED = 1, }; /** * enum qca_vendor_attr_btc_chain_mode - Specifies attributes for BT coex * chain mode. * Attributes for data used by QCA_NL80211_VENDOR_SUBCMD_BTC_CHAIN_MODE. * * @QCA_VENDOR_ATTR_COEX_BTC_CHAIN_MODE: u32 attribute. * Indicates the BT coex chain mode, are 32-bit values from * enum qca_btc_chain_mode. This attribute is mandatory. * * @QCA_VENDOR_ATTR_COEX_BTC_CHAIN_MODE_RESTART: flag attribute. * If set, vdev should be restarted when BT coex chain mode is updated. * This attribute is optional. */ enum qca_vendor_attr_btc_chain_mode { QCA_VENDOR_ATTR_BTC_CHAIN_MODE_INVALID = 0, QCA_VENDOR_ATTR_BTC_CHAIN_MODE = 1, QCA_VENDOR_ATTR_BTC_CHAIN_MODE_RESTART = 2, /* Keep last */ QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST, QCA_VENDOR_ATTR_BTC_CHAIN_MODE_MAX = QCA_VENDOR_ATTR_BTC_CHAIN_MODE_LAST - 1, }; /** * enum qca_vendor_wlan_sta_flags - Station feature flags * Bits will be set to 1 if the corresponding features are enabled. * @QCA_VENDOR_WLAN_STA_FLAG_AMPDU: AMPDU is enabled for the station * @QCA_VENDOR_WLAN_STA_FLAG_TX_STBC: TX Space-time block coding is enabled for the station * @QCA_VENDOR_WLAN_STA_FLAG_RX_STBC: RX Space-time block coding is enabled for the station */ enum qca_vendor_wlan_sta_flags { QCA_VENDOR_WLAN_STA_FLAG_AMPDU = BIT(0), QCA_VENDOR_WLAN_STA_FLAG_TX_STBC = BIT(1), QCA_VENDOR_WLAN_STA_FLAG_RX_STBC = BIT(2), }; /** * enum qca_vendor_wlan_sta_guard_interval - Station guard interval * @QCA_VENDOR_WLAN_STA_GI_800_NS: Legacy normal guard interval * @QCA_VENDOR_WLAN_STA_GI_400_NS: Legacy short guard interval * @QCA_VENDOR_WLAN_STA_GI_1600_NS: Guard interval used by HE * @QCA_VENDOR_WLAN_STA_GI_3200_NS: Guard interval used by HE */ enum qca_vendor_wlan_sta_guard_interval { QCA_VENDOR_WLAN_STA_GI_800_NS = 0, QCA_VENDOR_WLAN_STA_GI_400_NS = 1, QCA_VENDOR_WLAN_STA_GI_1600_NS = 2, QCA_VENDOR_WLAN_STA_GI_3200_NS = 3, }; /** * enum qca_wlan_vendor_attr_get_sta_info - Defines attributes * used by QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC: * Required attribute in request for AP mode only, 6-byte MAC address, * corresponding to the station's MAC address for which information is * requested. For STA mode this is not required as the info always correspond * to the self STA and the current/last association. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS: * Optionally used in response, u32 attribute, contains a bitmap of different * fields defined in enum qca_vendor_wlan_sta_flags, used in AP mode only. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL: * Optionally used in response, u32 attribute, possible values are defined in * enum qca_vendor_wlan_sta_guard_interval, used in AP mode only. * Guard interval used by the station. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT: * Optionally used in response, u32 attribute, used in AP mode only. * Value indicates the number of data frames received from station with retry * bit set to 1 in FC. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT: * Optionally used in response, u32 attribute, used in AP mode only. * Counter for number of data frames with broadcast or multicast address in * the destination address received from the station. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED: * Optionally used in response, u32 attribute, used in both STA and AP modes. * Value indicates the number of data frames successfully transmitted only * after retrying the packets and for which the TX status has been updated * back to host from target. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED: * Optionally used in response, u32 attribute, used in both STA and AP mode. * Value indicates the number of data frames not transmitted successfully even * after retrying the packets for the number of times equal to the total number * of retries allowed for that packet and for which the TX status has been * updated back to host from target. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL: * Optionally used in response, u32 attribute, used in AP mode only. * Counter in the target for the number of data frames successfully transmitted * to the station. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY: * Optionally used in response, u32 attribute, used in AP mode only. * Value indicates the number of data frames successfully transmitted only * after retrying the packets. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED: * Optionally used in response, u32 attribute, used in both STA & AP mode. * Value indicates the number of data frames not transmitted successfully even * after retrying the packets for the number of times equal to the total number * of retries allowed for that packet. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_PROBE_REQ_BMISS_COUNT: u32, used in * the STA mode only. Represent the number of probe requests sent by the STA * while attempting to roam on missing certain number of beacons from the * connected AP. If queried in the disconnected state, this represents the * count for the last connected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_PROBE_RESP_BMISS_COUNT: u32, used in * the STA mode. Represent the number of probe responses received by the station * while attempting to roam on missing certain number of beacons from the * connected AP. When queried in the disconnected state, this represents the * count when in last connected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_ALL_COUNT: u32, used in the * STA mode only. Represents the total number of frames sent out by STA * including Data, ACK, RTS, CTS, Control Management. This data is maintained * only for the connect session. Represents the count of last connected session, * when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_COUNT: u32, used in the STA mode. * Total number of RTS sent out by the STA. This data is maintained per connect * session. Represents the count of last connected session, when queried in the * disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_RETRY_FAIL_COUNT: u32, used in the * STA mode.Represent the number of RTS transmission failure that reach retry * limit. This data is maintained per connect session. Represents the count of * last connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_NON_AGGREGATED_COUNT: u32, used in * the STA mode. Represent the total number of non aggregated frames transmitted * by the STA. This data is maintained per connect session. Represents the count * of last connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_AGGREGATED_COUNT: u32, used in the * STA mode. Represent the total number of aggregated frames transmitted by the * STA. This data is maintained per connect session. Represents the count of * last connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_GOOD_PLCP_COUNT: u32, used in * the STA mode. Represents the number of received frames with a good PLCP. This * data is maintained per connect session. Represents the count of last * connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_INVALID_DELIMITER_COUNT: u32, * used in the STA mode. Represents the number of occasions that no valid * delimiter is detected by A-MPDU parser. This data is maintained per connect * session. Represents the count of last connected session, when queried in the * disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_CRC_FAIL_COUNT: u32, used in the * STA mode. Represents the number of frames for which CRC check failed in the * MAC. This data is maintained per connect session. Represents the count of * last connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_ACKS_GOOD_FCS_COUNT: u32, used in the * STA mode. Represents the number of unicast ACKs received with good FCS. This * data is maintained per connect session. Represents the count of last * connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BLOCKACK_COUNT: u32, used in the STA * mode. Represents the number of received Block Acks. This data is maintained * per connect session. Represents the count of last connected session, when * queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BEACON_COUNT: u32, used in the STA * mode. Represents the number of beacons received from the connected BSS. This * data is maintained per connect session. Represents the count of last * connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_OTHER_BEACON_COUNT: u32, used in the * STA mode. Represents the number of beacons received by the other BSS when in * connected state (through the probes done by the STA). This data is maintained * per connect session. Represents the count of last connected session, when * queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_UCAST_DATA_GOOD_FCS_COUNT: u64, used in * the STA mode. Represents the number of received DATA frames with good FCS and * matching Receiver Address when in connected state. This data is maintained * per connect session. Represents the count of last connected session, when * queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_DATA_BC_MC_DROP_COUNT: u32, used in the * STA mode. Represents the number of RX Data multicast frames dropped by the HW * when in the connected state. This data is maintained per connect session. * Represents the count of last connected session, when queried in the * disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_1MBPS: u32, used in the * STA mode. This represents the target power in dBm for the transmissions done * to the AP in 2.4 GHz at 1 Mbps (DSSS) rate. This data is maintained per * connect session. Represents the count of last connected session, when * queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_6MBPS: u32, used in the * STA mode. This represents the Target power in dBm for transmissions done to * the AP in 2.4 GHz at 6 Mbps (OFDM) rate. This data is maintained per connect * session. Represents the count of last connected session, when queried in the * disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_MCS0: u32, used in the * STA mode. This represents the Target power in dBm for transmissions done to * the AP in 2.4 GHz at MCS0 rate. This data is maintained per connect session. * Represents the count of last connected session, when queried in the * disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_6MBPS: u32, used in the * STA mode. This represents the Target power in dBm for transmissions done to * the AP in 5 GHz at 6 Mbps (OFDM) rate. This data is maintained per connect * session. Represents the count of last connected session, when queried in * the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_MCS0: u32, used in the * STA mode. This represents the Target power in dBm for for transmissions done * to the AP in 5 GHz at MCS0 rate. This data is maintained per connect session. * Represents the count of last connected session, when queried in the * disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_HW_BUFFERS_OVERFLOW_COUNT: u32, used * in the STA mode. This represents the Nested attribute representing the * overflow counts of each receive buffer allocated to the hardware during the * STA's connection. The number of hw buffers might vary for each WLAN * solution and hence this attribute represents the nested array of all such * HW buffer count. This data is maintained per connect session. Represents * the count of last connected session, when queried in the disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX_TX_POWER: u32, Max TX power (dBm) * allowed as per the regulatory requirements for the current or last connected * session. Used in the STA mode. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_POWER: u32, Latest TX power * (dBm) used by the station in its latest unicast frame while communicating * to the AP in the connected state. When queried in the disconnected state, * this represents the TX power used by the STA with last AP communication * when in connected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ANI_LEVEL: u32, Adaptive noise immunity * level used to adjust the RX sensitivity. Represents the current ANI level * when queried in the connected state. When queried in the disconnected * state, this corresponds to the latest ANI level at the instance of * disconnection. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_IES: Binary attribute containing * the raw information elements from Beacon frames. Represents the Beacon frames * of the current BSS in the connected state. When queried in the disconnected * state, these IEs correspond to the last connected BSSID. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PROBE_RESP_IES: Binary attribute * containing the raw information elements from Probe Response frames. * Represents the Probe Response frames of the current BSS in the connected * state. When queried in the disconnected state, these IEs correspond to the * last connected BSSID. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_DRIVER_DISCONNECT_REASON: u32, Driver * disconnect reason for the last disconnection if the disconnection is * triggered from the host driver. The values are referred from * enum qca_disconnect_reason_codes. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT: u32, used in STA mode * only. This represents the number of group addressed robust management frames * received from this station with an invalid MIC or a missing MME when PMF is * enabled. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT: u32, used in STA mode * only. This represents the number of group addressed robust management frames * received from this station with the packet number less than or equal to the * last received packet number when PMF is enabled. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT: u32, used in STA * mode only. This represents the number of Beacon frames received from this * station with an invalid MIC or a missing MME when beacon protection is * enabled. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode * only. This represents number of Beacon frames received from this station with * the packet number less than or equal to the last received packet number when * beacon protection is enabled. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in * STA mode only. The driver uses this attribute to populate the connection * failure reason codes and the values are defined in * enum qca_sta_connect_fail_reason_codes. Userspace applications can send * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving * a connection failure indication from the driver. The driver shall not * include this attribute in response to the * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no connection * failure observed in the last attempted connection. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE: u32, latest TX rate (Kbps) * used by the station in its last TX frame while communicating to the AP in the * connected state. When queried in the disconnected state, this represents the * rate used by the STA in the last TX frame to the AP when it was connected. * This attribute is used for STA mode only. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX: u32, used in STA mode only. * This represents the rate index used by the STA for the last TX frame to the * AP. When queried in the disconnected state, this gives the last RIX used by * the STA in the last TX frame to the AP when it was connected. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT: u32, used in STA * mode only. This represents the number of times the STA TSF goes out of sync * from the AP after the connection. If queried in the disconnected state, this * gives the count of TSF out of sync for the last connection. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON: u32, used in STA * mode only. This represents the roam trigger reason for the last roaming * attempted by the firmware. This can be queried either in connected state or * disconnected state. Each bit of this attribute represents the different * roam trigger reason code which are defined in enum qca_vendor_roam_triggers. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON: u32, used in STA mode * only. This represents the roam fail reason for the last failed roaming * attempt by the firmware. Different roam failure reason codes are specified * in enum qca_vendor_roam_fail_reasons. This can be queried either in * connected state or disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON: u32, used in * STA mode only. This represents the roam invoke fail reason for the last * failed roam invoke. Different roam invoke failure reason codes * are specified in enum qca_vendor_roam_invoke_fail_reasons. This can be * queried either in connected state or disconnected state. * * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY: u32, used in STA mode only. * This represents the average congestion duration of uplink frames in MAC * queue in unit of ms. This can be queried either in connected state or * disconnected state. */ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAC = 1, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_FLAGS = 2, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_GUARD_INTERVAL = 3, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_RETRY_COUNT = 4, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BC_MC_COUNT = 5, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_SUCCEED = 6, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RETRY_EXHAUSTED = 7, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_TOTAL = 8, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY = 9, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_RETRY_EXHAUSTED = 10, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_PROBE_REQ_BMISS_COUNT = 11, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_PROBE_RESP_BMISS_COUNT = 12, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_TX_ALL_COUNT = 13, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_COUNT = 14, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_RTS_RETRY_FAIL_COUNT = 15, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_NON_AGGREGATED_COUNT = 16, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TX_DATA_AGGREGATED_COUNT = 17, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_GOOD_PLCP_COUNT = 18, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_INVALID_DELIMITER_COUNT = 19, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_FRAMES_CRC_FAIL_COUNT = 20, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_ACKS_GOOD_FCS_COUNT = 21, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BLOCKACK_COUNT = 22, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_BEACON_COUNT = 23, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_OTHER_BEACON_COUNT = 24, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_UCAST_DATA_GOOD_FCS_COUNT = 25, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_DATA_BC_MC_DROP_COUNT = 26, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_1MBPS = 27, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_6MBPS = 28, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_24G_MCS0 = 29, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_6MBPS = 30, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TARGET_POWER_5G_MCS0 = 31, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_RX_HW_BUFFERS_OVERFLOW_COUNT = 32, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX_TX_POWER = 33, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_POWER = 34, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ANI_LEVEL = 35, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_IES = 36, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PROBE_RESP_IES = 37, QCA_WLAN_VENDOR_ATTR_GET_STA_DRIVER_DISCONNECT_REASON = 38, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT = 39, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_TX_RATE = 44, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_LATEST_RIX = 45, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_TSF_OUT_OF_SYNC_COUNT = 46, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_TRIGGER_REASON = 47, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_FAIL_REASON = 48, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_ROAM_INVOKE_FAIL_REASON = 49, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_UPLINK_DELAY = 50, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX = QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_update_sta_info - Defines attributes * used by QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO vendor command. * * @QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS: Type is NLA_UNSPEC. * Used in STA mode. This attribute represents the list of channel center * frequencies in MHz (u32) the station has learnt during the last connection * or roaming attempt. This information shall not signify the channels for * an explicit scan request from the user space. Host drivers can update this * information to the user space in both connected and disconnected state. * In the disconnected state this information shall signify the channels * scanned in the last connection/roam attempt that lead to the disconnection. */ enum qca_wlan_vendor_attr_update_sta_info { QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_INVALID = 0, QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_CONNECT_CHANNELS = 1, /* keep last */ QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_MAX = QCA_WLAN_VENDOR_ATTR_UPDATE_STA_INFO_AFTER_LAST - 1, }; /** * enum qca_disconnect_reason_codes - Specifies driver disconnect reason codes. * Used when the driver triggers the STA to disconnect from the AP. * * @QCA_DISCONNECT_REASON_UNSPECIFIED: The host driver triggered the * disconnection with the AP due to unspecified reasons. * * @QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE: The host driver triggered the * disconnection with the AP due to a roaming failure. This roaming is triggered * internally (host driver/firmware). * * @QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE: The driver disconnected from * the AP when the user/external triggered roaming fails. * * @QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE: This reason code is used * by the host driver whenever gateway reachability failure is detected and the * driver disconnects with AP. * * @QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA: The driver disconnected from * the AP on a channel switch announcement from it with an unsupported channel. * * @QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR: On a concurrent AP start * with indoor channels disabled and if the STA is connected on one of these * disabled channels, the host driver disconnected the STA with this reason * code. * * @QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED: Disconnection due to an * explicit request from the user to disable the current operating channel. * * @QCA_DISCONNECT_REASON_DEVICE_RECOVERY: STA disconnected from the AP due to * the internal host driver/firmware recovery. * * @QCA_DISCONNECT_REASON_KEY_TIMEOUT: The driver triggered the disconnection on * a timeout for the key installations from the user space. * * @QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE: The dDriver disconnected the * STA on a band change request from the user space to a different band from the * current operation channel/band. * * @QCA_DISCONNECT_REASON_IFACE_DOWN: The STA disconnected from the AP on an * interface down trigger from the user space. * * @QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL: The host driver disconnected the * STA on getting continuous transmission failures for multiple Data frames. * * @QCA_DISCONNECT_REASON_PEER_INACTIVITY: The STA does a keep alive * notification to the AP by transmitting NULL/G-ARP frames. This disconnection * represents inactivity from AP on such transmissions. * @QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT: This reason code is used on * disconnection when SA Query times out (AP does not respond to SA Query). * * @QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE: The host driver disconnected the * STA on missing the beacons continuously from the AP. * * @QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE: Disconnection due to STA not * able to move to the channel mentioned by the AP in CSA. * * @QCA_DISCONNECT_REASON_USER_TRIGGERED: User triggered disconnection. */ enum qca_disconnect_reason_codes { QCA_DISCONNECT_REASON_UNSPECIFIED = 0, QCA_DISCONNECT_REASON_INTERNAL_ROAM_FAILURE = 1, QCA_DISCONNECT_REASON_EXTERNAL_ROAM_FAILURE = 2, QCA_DISCONNECT_REASON_GATEWAY_REACHABILITY_FAILURE = 3, QCA_DISCONNECT_REASON_UNSUPPORTED_CHANNEL_CSA = 4, QCA_DISCONNECT_REASON_OPER_CHANNEL_DISABLED_INDOOR = 5, QCA_DISCONNECT_REASON_OPER_CHANNEL_USER_DISABLED = 6, QCA_DISCONNECT_REASON_DEVICE_RECOVERY = 7, QCA_DISCONNECT_REASON_KEY_TIMEOUT = 8, QCA_DISCONNECT_REASON_OPER_CHANNEL_BAND_CHANGE = 9, QCA_DISCONNECT_REASON_IFACE_DOWN = 10, QCA_DISCONNECT_REASON_PEER_XRETRY_FAIL = 11, QCA_DISCONNECT_REASON_PEER_INACTIVITY = 12, QCA_DISCONNECT_REASON_SA_QUERY_TIMEOUT = 13, QCA_DISCONNECT_REASON_BEACON_MISS_FAILURE = 14, QCA_DISCONNECT_REASON_CHANNEL_SWITCH_FAILURE = 15, QCA_DISCONNECT_REASON_USER_TRIGGERED = 16, }; /** * enum qca_wlan_vendor_attr_driver_disconnect_reason - Defines attributes * used by %QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON vendor command. * * @QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASCON_CODE: u32 attribute. * This attribute represents the driver specific reason codes (local * driver/firmware initiated reasons for disconnection) defined * in enum qca_disconnect_reason_codes. */ enum qca_wlan_vendor_attr_driver_disconnect_reason { QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASON_INVALID = 0, QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASCON_CODE = 1, /* keep last */ QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASON_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASON_MAX = QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASON_AFTER_LAST - 1, }; /** * enum qca_wlan_tspec_operation - Operation of the config TSPEC request * * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION. */ enum qca_wlan_tspec_operation { QCA_WLAN_TSPEC_ADD = 0, QCA_WLAN_TSPEC_DEL = 1, QCA_WLAN_TSPEC_GET = 2, }; /** * enum qca_wlan_tspec_direction - Direction in TSPEC * As what is defined in IEEE Std 802.11-2016, Table 9-139. * * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION. */ enum qca_wlan_tspec_direction { QCA_WLAN_TSPEC_DIRECTION_UPLINK = 0, QCA_WLAN_TSPEC_DIRECTION_DOWNLINK = 1, QCA_WLAN_TSPEC_DIRECTION_DIRECT = 2, QCA_WLAN_TSPEC_DIRECTION_BOTH = 3, }; /** * enum qca_wlan_tspec_ack_policy - MAC acknowledgement policy in TSPEC * As what is defined in IEEE Std 802.11-2016, Table 9-141. * * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY. */ enum qca_wlan_tspec_ack_policy { QCA_WLAN_TSPEC_NORMAL_ACK = 0, QCA_WLAN_TSPEC_NO_ACK = 1, /* Reserved */ QCA_WLAN_TSPEC_BLOCK_ACK = 3, }; /** * enum qca_wlan_vendor_attr_config_tspec - Defines attributes * used by %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC vendor command. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION: * u8 attribute. Specify the TSPEC operation of this request. Possible values * are defined in enum qca_wlan_tspec_operation. * Mandatory attribute for all kinds of config TSPEC requests. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_TSID: * u8 attribute. TS ID. Possible values are 0-7. * Applicable for operation: QCA_WLAN_TSPEC_ADD, QCA_WLAN_TSPEC_DEL, * QCA_WLAN_TSPEC_GET. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION: * u8 attribute. Direction of data carried by the TS. Possible values are * defined in enum qca_wlan_tspec_direction. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_APSD: * Flag attribute. Indicate whether APSD is enabled for the traffic associated * with the TS. set - enabled, not set - disabled. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_USER_PRIORITY: * u8 attribute. User priority to be used for the transport of MSDUs/A-MSDUs * belonging to this TS. Possible values are 0-7. * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY: * u8 attribute. Indicate whether MAC acknowledgements are required for * MPDUs/A-MSDUs belonging to this TS and the form of those acknowledgements. * Possible values are defined in enum qca_wlan_tspec_ack_policy. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_NOMINAL_MSDU_SIZE: * u16 attribute. Specify the nominal size in bytes of MSDUs/A-MSDUs * belonging to this TS. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAXIMUM_MSDU_SIZE: * u16 attribute. Specify the maximum size in bytes of MSDUs/A-MSDUs * belonging to this TS. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MIN_SERVICE_INTERVAL: * u32 attribute. Specify the minimum interval in microseconds between the * start of two successive SPs. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX_SERVICE_INTERVAL: * u32 attribute. Specify the maximum interval in microseconds between the * start of two successive SPs. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INACTIVITY_INTERVAL: * u32 attribute. Specify the minimum interval in microseconds that can elapse * without arrival or transfer of an MPDU belonging to the TS before this TS * is deleted by the MAC entity at the HC. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SUSPENSION_INTERVAL: * u32 attribute. Specify the minimum interval in microseconds that can elapse * without arrival or transfer of an MSDU belonging to the TS before the * generation of successive QoS(+)CF-Poll is stopped for this TS. A value of * 0xFFFFFFFF disables the suspension interval. The value of the suspension * interval is always less than or equal to the inactivity interval. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_DATA_RATE: * u32 attribute. Indicate the lowest data rate in bps specified at the MAC * SAP for transport of MSDUs or A-MSDUs belonging to this TS within the * bounds of this TSPEC. * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MEAN_DATA_RATE: * u32 attribute. Indicate the average data rate in bps specified at the MAC * SAP for transport of MSDUs or A-MSDUs belonging to this TS within the * bounds of this TSPEC. * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_PEAK_DATA_RATE: * u32 attribute. Indicate the maximum allowable data rate in bps specified at * the MAC SAP for transport of MSDUs or A-MSDUs belonging to this TS within * the bounds of this TSPEC. * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_BURST_SIZE: * u32 attribute. Specify the maximum burst size in bytes of the MSDUs/A-MSDUs * belonging to this TS that arrive at the MAC SAP at the peak data rate. A * value of 0 indicates that there are no bursts. * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_PHY_RATE: * u32 attribute. Indicate the minimum PHY rate in bps for transport of * MSDUs/A-MSDUs belonging to this TS within the bounds of this TSPEC. * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. * * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SURPLUS_BANDWIDTH_ALLOWANCE: * u16 attribute. Specify the excess allocation of time (and bandwidth) over * and above the stated application rates required to transport an MSDU/A-MSDU * belonging to the TS in this TSPEC. * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. */ enum qca_wlan_vendor_attr_config_tspec { QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INVALID = 0, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION = 1, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_TSID = 2, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION = 3, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_APSD = 4, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_USER_PRIORITY = 5, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY = 6, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_NOMINAL_MSDU_SIZE = 7, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAXIMUM_MSDU_SIZE = 8, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MIN_SERVICE_INTERVAL = 9, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX_SERVICE_INTERVAL = 10, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INACTIVITY_INTERVAL = 11, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SUSPENSION_INTERVAL = 12, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_DATA_RATE = 13, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MEAN_DATA_RATE = 14, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_PEAK_DATA_RATE = 15, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_BURST_SIZE = 16, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_PHY_RATE = 17, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SURPLUS_BANDWIDTH_ALLOWANCE = 18, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX = QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_oci_override_frame_type - OCI override frame type * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ: SA Query Request frame * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP: SA Query Response frame * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ: FT Reassociation Request * frame * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ: FILS Reassociation * Request frame. */ enum qca_wlan_vendor_oci_override_frame_type { QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ = 1, QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP = 2, QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ = 3, QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ = 4, }; /** * enum qca_wlan_vendor_attr_oci_override: Represents attributes for * OCI override request. These attributes are used inside nested attribute * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE in QCA vendor command * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. * * @QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE: Required attribute, u8. * Values from enum qca_wlan_vendor_oci_override_frame_type used in this * attribute to specify the frame type in which the OCI is to be overridden. * * @QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY: Required (u32) * OCI frequency (in MHz) to override in the specified frame type. */ enum qca_wlan_vendor_attr_oci_override { QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE = 1, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY = 2, /* keep last */ QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX = QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST - 1, }; /** * enum qca_wlan_medium_assess_type - Type of medium assess request * * Values for %QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE. */ enum qca_wlan_medium_assess_type { QCA_WLAN_MEDIUM_ASSESS_CCA = 0, QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT = 1, }; /** * enum qca_wlan_vendor_attr_medium_assess - Attributes used by * %QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS vendor command. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE: * u8 attribute. Mandatory in all kinds of medium assess requests/responses. * Specify the type of medium assess request and indicate its type in response. * Possible values are defined in enum qca_wlan_medium_assess_type. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_PERIOD: * u32 attribute. Mandatory in CCA request. * Specify the assessment period in terms of seconds. Assessment result will be * sent as the response to the CCA request after the assessment period. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT: * u32 attribute. Mandatory in response to CCA request. * Total timer tick count of the assessment cycle. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT: * u32 attribute. Mandatory in response to CCA request. * Timer tick count of idle time in the assessment cycle. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT: * u32 attribute. Mandatory in response to CCA request. * Timer tick count of Intra BSS traffic RX time in the assessment cycle. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT: * u32 attribute. Mandatory in response to CCA request. * Timer tick count of Overlapping BSS traffic RX time in the assessment cycle. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI: * s32 attribute. Mandatory in response to CCA request. * Maximum RSSI of Intra BSS traffic in the assessment cycle. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI: * s32 attribute. Mandatory in response to CCA request. * Minimum RSSI of Intra BSS traffic in the assessment cycle. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE: * u8 attribute. Mandatory in congestion report request. * 1-enable 0-disable. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD: * u8 attribute. Mandatory in congestion report enable request and will be * ignored if present in congestion report disable request. Possible values are * 0-100. A vendor event QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS with the type * QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT will be sent to userspace if * congestion percentage reaches the configured threshold. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL: * u8 attribute. Optional in congestion report enable request and will be * ignored if present in congestion report disable request. * Specify the interval of congestion report event in terms of seconds. Possible * values are 1-255. Default value 1 will be used if this attribute is omitted * or using invalid values. * * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_PERCENTAGE: * u8 attribute. Mandatory in congestion report event. * Indicate the actual congestion percentage. Possible values are 0-100. */ enum qca_wlan_vendor_attr_medium_assess { QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE = 1, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_PERIOD = 2, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT = 3, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT = 4, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT = 5, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT = 6, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI = 7, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI = 8, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE = 9, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD = 10, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL = 11, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_PERCENTAGE = 12, /* keep last */ QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX = QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_mbssid_tx_vdev_status - Defines attributes * used by QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS vendor command. * * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL: * u8 attribute. Notify the TX VDEV status. Possible values 0, 1 * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV, * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events. * * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT: * u8 attribute, required. 1 means Tx VDEV up event. 0 means Tx VDEV down event. * * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID: * u8 attribute, required. Indicates group id of Tx VDEV. * * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO: * Nested attribute. This attribute shall be used by the driver to send * group information. The attributes defined in enum * qca_wlan_vendor_attr_mbssid_tx_vdev_group_info * are nested in this attribute. */ enum qca_wlan_vendor_attr_mbssid_tx_vdev_status { QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_EVENT = 2, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_ID = 3, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_MAX = QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info - Attributes used * inside %QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO nested attribute. * * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX: * u32 attribute, required. Contains interface index. * * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS: * u8 attribute, required. 0 - means vdev is in down state. * 1 - means vdev is in up state. */ enum qca_wlan_vendor_attr_mbssid_tx_vdev_group_info { QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_INVALID = 0, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_IF_INDEX = 1, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_STATUS = 2, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO_MAX = QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_GROUP_INFO - 1, }; /** * enum qca_wlan_concurrent_sta_policy_config - Concurrent STA policies * * @QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY: Preference to the primary * STA interface has to be given while selecting the connection policies * (e.g., BSSID, band, TX/RX chains, etc.) for the subsequent STA interface. * An interface is set as primary through the attribute * QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY. This policy is not * applicable if the primary interface has not been set earlier. * * The intention is not to downgrade the primary STA performance, such as: * - Do not reduce the number of TX/RX chains of primary connection. * - Do not optimize DBS vs. MCC/SCC, if DBS ends up reducing the number of * chains. * - If using MCC, should set the MCC duty cycle of the primary connection to * be higher than the secondary connection. * * @QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED: The connection policies for the * subsequent STA connection shall be chosen to balance with the existing * concurrent STA's performance. * Such as * - Can choose MCC or DBS mode depending on the MCC efficiency and hardware * capability. * - If using MCC, set the MCC duty cycle of the primary connection to be equal * to the secondary. * - Prefer BSSID candidates which will help provide the best "overall" * performance for all the STA connections. */ enum qca_wlan_concurrent_sta_policy_config { QCA_WLAN_CONCURRENT_STA_POLICY_PREFER_PRIMARY = 0, QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED = 1, }; /** * enum qca_wlan_vendor_attr_concurrent_sta_policy - Defines attributes * used by QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY vendor command. * * @QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG: * u8 attribute. Configures the concurrent STA policy configuration. * Possible values are defined in enum qca_wlan_concurrent_sta_policy_config. */ enum qca_wlan_vendor_attr_concurrent_sta_policy { QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_INVALID = 0, QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG = 1, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX = QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_AFTER_LAST - 1, }; /** * enum qca_sta_connect_fail_reason_codes - Defines values carried * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor * attribute. * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received * for unicast Probe Request frame. * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request. * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for * auth request. * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not * received from AP. * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send * Association Request frame. * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for * Association Request frame. * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response * frame is not received from AP. */ enum qca_sta_connect_fail_reason_codes { QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1, QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2, QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3, QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4, QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5, QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6, QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7, }; /** * enum qca_wlan_vendor_usable_channels_filter - Bitmask of different * filters defined in this enum are used in attribute * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK. * * @QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX: When this bit is set, the driver * shall filter the channels which are not usable because of coexistence with * cellular radio. * @QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY: When this bit is set, the driver * shall filter the channels which are not usable because of existing active * interfaces in the driver and will result in Multi Channel Concurrency, etc. * */ enum qca_wlan_vendor_usable_channels_filter { QCA_WLAN_VENDOR_FILTER_CELLULAR_COEX = 0, QCA_WLAN_VENDOR_FILTER_WLAN_CONCURRENCY = 1, }; /** * enum qca_wlan_vendor_attr_chan_info - Attributes used inside * %QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO nested attribute. * * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ: * u32 attribute, required. Indicates the center frequency of the primary * channel in MHz. * * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ: * u32 attribute. Indicates the center frequency of the primary segment of the * channel in MHz. This attribute is required when reporting 40 MHz, 80 MHz, * 160 MHz, and 320 MHz channels. * * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ: * u32 attribute. Indicates the center frequency of the secondary segment of * 80+80 channel in MHz. This attribute is required only when * QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH is set to NL80211_CHAN_WIDTH_80P80. * * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH: * u32 attribute, required. Indicates the bandwidth of the channel, possible * values are defined in enum nl80211_chan_width. * * @QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK: * u32 attribute, required. Indicates all the interface types for which this * channel is usable. This attribute encapsulates bitmasks of interface types * defined in enum nl80211_iftype. * */ enum qca_wlan_vendor_attr_chan_info { QCA_WLAN_VENDOR_ATTR_CHAN_INFO_INVALID = 0, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ = 1, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG0_FREQ = 2, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_SEG1_FREQ = 3, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH = 4, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX = QCA_WLAN_VENDOR_ATTR_CHAN_INFO_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_usable_channels - Attributes used by * %QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS vendor command. * * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK: * u32 attribute. Indicates the bands from which the channels should be reported * in response. This attribute encapsulates bit masks of bands defined in enum * nl80211_band. Optional attribute, if not present in the request the driver * shall return channels from all supported bands. * * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK: * u32 attribute. Indicates all the interface types for which the usable * channels information is requested. This attribute encapsulates bitmasks of * interface types defined in enum nl80211_iftype. Optional attribute, if not * present in the request the driver shall send information of all supported * interface modes. * * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK: * u32 attribute. This attribute carries information of all filters that shall * be applied while populating usable channels information by the driver. This * attribute carries bit masks of different filters defined in enum * qca_wlan_vendor_usable_channels_filter. Optional attribute, if not present * in the request the driver shall send information of channels without applying * any of the filters that can be configured through this attribute. * * @QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO: * Nested attribute. This attribute shall be used by the driver to send * usability information of each channel. The attributes defined in enum * qca_wlan_vendor_attr_chan_info are used inside this attribute. */ enum qca_wlan_vendor_attr_usable_channels { QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_BAND_MASK = 1, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_IFACE_MODE_MASK = 2, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_FILTER_MASK = 3, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX = QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_radar_history: Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY to get DFS radar history. * * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES: Nested attribute to carry * the list of radar history entries. * Each entry contains freq, timestamp, and radar signal detect flag. * The driver shall add an entry when CAC has finished, or radar signal * has been detected post AP beaconing. The driver shall maintain at least * 8 entries in order to save CAC result for a 160 MHz channel. * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ: u32 attribute. * Channel frequency in MHz. * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP: u64 nanoseconds. * CLOCK_BOOTTIME timestamp when this entry is updated due to CAC * or radar detection. * @QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED: NLA_FLAG attribute. * This flag indicates radar signal has been detected. */ enum qca_wlan_vendor_attr_radar_history { QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_INVALID = 0, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_ENTRIES = 1, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_FREQ = 2, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_TIMESTAMP = 3, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_DETECTED = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST, QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_MAX = QCA_WLAN_VENDOR_ATTR_RADAR_HISTORY_LAST - 1, }; /** * enum qca_wlan_vendor_attr_mdns_offload - Attributes used by * %QCA_NL80211_VENDOR_SUBCMD_MDNS_OFFLOAD vendor command. * * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE: Required (flag) * Enable mDNS offload. This attribute is mandatory to enable * mDNS offload feature. If this attribute is not present, mDNS offload * is disabled. * * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE: Nested attribute containing * one or more %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY attributes. This * attribute is mandatory when enabling the feature, and not required when * disabling the feature. * * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY: Nested attribute containing * the following attributes: * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT * %QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD * * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN: Required string attribute. * It consists of a hostname and ".local" as the domain name. The character * set is limited to UTF-8 encoding. The maximum allowed size is 63 bytes. * It is used to compare the domain in the "QU" query. Only 1 FQDN is * supported per vdev. * For example: myphone.local * * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT: Required * u16 attribute. It specifies the total number of resource records present * in the answer section of the answer payload. This attribute is needed by the * firmware to populate the mDNS response frame for mDNS queries without having * to parse the answer payload. * * @QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD: Required binary blob * attribute sent by the mdnsResponder from userspace. It contains resource * records of various types (e.g., A, AAAA, PTR, TXT) and service list. This * payload is passed down to the firmware and is transmitted in response to * mDNS queries. * The maximum supported size of the answer payload is 512 bytes. */ enum qca_wlan_vendor_attr_mdns_offload { QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_INVALID = 0, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENABLE = 1, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_TABLE = 2, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ENTRY = 3, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_FQDN = 4, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_RESOURCE_RECORDS_COUNT = 5, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_ANSWER_PAYLOAD = 6, /* keep last */ QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_MAX = QCA_WLAN_VENDOR_ATTR_MDNS_OFFLOAD_AFTER_LAST - 1, }; /** * qca_wlan_vendor_monitor_data_frame_type - Represent the various * Data frame types to be sent over the monitor interface. */ enum qca_wlan_vendor_monitor_data_frame_type { QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL = BIT(0), /* valid only if QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ALL is not set */ QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ARP = BIT(1), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV4 = BIT(2), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DHCPV6 = BIT(3), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_EAPOL = BIT(4), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV4 = BIT(5), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_DNSV6 = BIT(6), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYN = BIT(7), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_SYNACK = BIT(8), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FIN = BIT(9), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_FINACK = BIT(10), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_ACK = BIT(11), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_TCP_RST = BIT(12), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV4 = BIT(13), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_ICMPV6 = BIT(14), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_RTP = BIT(15), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_TYPE_SIP = BIT(16), QCA_WLAN_VENDOR_MONITOR_DATA_FRAME_QOS_NULL = BIT(17), }; /** * qca_wlan_vendor_monitor_mgmt_frame_type - Represent the various * Management frame types to be sent over the monitor interface. * @QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL: All the Management Frames. * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_NO_BEACON: All the Management frames * except the Beacon frame. * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON: Only the connected * BSSID Beacon frames. Valid only in the connected state. * @QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON: Represents * the Beacon frames obtained during the scan (off channel and connected * channel), when in connected state. */ enum qca_wlan_vendor_monitor_mgmt_frame_type { QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL = BIT(0), /* valid only if QCA_WLAN_VENDOR_MONITOR_MGMT_FRAME_TYPE_ALL is not set */ QCA_WLAN_VENDOR_MONITOR_MGMT_NO_BEACON = BIT(1), QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_BEACON = BIT(2), QCA_WLAN_VENDOR_MONITOR_MGMT_CONNECT_SCAN_BEACON = BIT(3), }; /** * qca_wlan_vendor_monitor_ctrl_frame_type - Represent the various * Control frame types to be sent over the monitor interface. * @QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL: All the Control frames * @QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME: Trigger frame */ enum qca_wlan_vendor_monitor_ctrl_frame_type { QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL = BIT(0), /* valid only if QCA_WLAN_VENDOR_MONITOR_CTRL_FRAME_TYPE_ALL is not set */ QCA_WLAN_VENDOR_MONITOR_CTRL_TRIGGER_FRAME = BIT(1), }; /** * enum qca_wlan_vendor_attr_set_monitor_mode - Used by the * vendor command QCA_NL80211_VENDOR_SUBCMD_SET_MONITOR_MODE to set the * monitor mode. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE: u32 attribute. * Represents the TX Data frame types to be monitored (u32). These Data frames * are represented by enum qca_wlan_vendor_monitor_data_frame_type. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE: u32 attribute. * Represents the RX Data frame types to be monitored (u32). These Data frames * are represented by enum qca_wlan_vendor_monitor_data_frame_type. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE: u32 attribute. * Represents the TX Management frame types to be monitored (u32). These * Management frames are represented by * enum qca_wlan_vendor_monitor_mgmt_frame_type. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE: u32 attribute. * Represents the RX Management frame types to be monitored (u32). These * Management frames are represented by * enum qca_wlan_vendor_monitor_mgmt_frame_type. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE: u32 attribute. * Represents the TX Control frame types to be monitored (u32). These Control * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE: u32 attribute. * Represents the RX Control frame types to be monitored (u32). These Control * frames are represented by enum qca_wlan_vendor_monitor_ctrl_frame_type. * * @QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL: u32 * attribute. * Represents the interval in milliseconds only for the connected Beacon frames, * expecting the connected BSS's Beacon frames to be sent on the monitor * interface at this specific interval. */ enum qca_wlan_vendor_attr_set_monitor_mode { QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_INVALID = 0, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_TX_FRAME_TYPE = 1, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_DATA_RX_FRAME_TYPE = 2, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_TX_FRAME_TYPE = 3, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MGMT_RX_FRAME_TYPE = 4, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_TX_FRAME_TYPE = 5, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CTRL_RX_FRAME_TYPE = 6, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_CONNECTED_BEACON_INTERVAL = 7, /* keep last */ QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_MAX = QCA_WLAN_VENDOR_ATTR_SET_MONITOR_MODE_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_roam_scan_state - Roam scan state flags. * Bits will be set to 1 if the corresponding state is enabled. * * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_START: Scan Start. * @QCA_VENDOR_WLAN_ROAM_SCAN_STATE_END: Scan end. */ enum qca_wlan_vendor_roam_scan_state { QCA_WLAN_VENDOR_ROAM_SCAN_STATE_START = BIT(0), QCA_WLAN_VENDOR_ROAM_SCAN_STATE_END = BIT(1), }; /** * enum qca_wlan_vendor_roam_event_type - Roam event type flags. * Bits will be set to 1 if the corresponding event is notified. * * @QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON: Represents that the roam event * carries the trigger reason. When set, it is expected that the roam event * carries the respective reason via the attribute * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON. This event also carries * the BSSID, RSSI, frequency info of the AP to which the roam is attempted. * * @QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON: Represents that the roam event * carries the roam fail reason. When set, it is expected that the roam event * carries the respective reason via the attribute * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_FAIL_REASON. This event also carries the * BSSID, RSSI, frequency info of the AP to which the roam was attempted. * * @QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON: Represents that the roam * event carries the roam invoke fail reason. When set, it is expected that * the roam event carries the respective reason via the attribute * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON. * * @QCA_WLAN_VENDOR_ROAM_EVENT_SCAN_STATE: Represents that the roam event * carries the roam scan state. When set, it is expected that the roam event * carries the respective scan state via the attribute * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE and the corresponding * frequency info via QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST. */ enum qca_wlan_vendor_roam_event_type { QCA_WLAN_VENDOR_ROAM_EVENT_TRIGGER_REASON = BIT(0), QCA_WLAN_VENDOR_ROAM_EVENT_FAIL_REASON = BIT(1), QCA_WLAN_VENDOR_ROAM_EVENT_INVOKE_FAIL_REASON = BIT(2), QCA_WLAN_VENDOR_ROAM_EVENT_ROAM_SCAN_STATE = BIT(3), }; /** * enum qca_wlan_vendor_attr_roam_events_candidate_info: Roam candidate info. * Referred by QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID: 6-byte MAC address * representing the BSSID of the AP to which the roam is attempted. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI: Signed 32-bit value * in dBm, signifying the RSSI of the candidate BSSID to which the Roaming is * attempted. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ: u32, frequency in MHz * on which the roam is attempted. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON: u32, used in * STA mode only. This represents the roam fail reason for the last failed * roaming attempt by the firmware for the specific BSSID. Different roam * failure reason codes are specified in enum qca_vendor_roam_fail_reasons. */ enum qca_wlan_vendor_attr_roam_events_candidate_info { QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_BSSID = 1, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_RSSI = 2, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FREQ = 3, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_FAIL_REASON = 4, /* keep last */ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_MAX = QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO_AFTER_LAST - 1, }; /** * enum qca_wlan_vendor_attr_roam_events - Used by the * vendor command QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS to either configure the * roam events to the driver or notify these events from the driver. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE: u8 attribute. Configures the * driver/firmware to enable/disable the notification of roam events. It's a * mandatory attribute and used only in the request from the userspace to the * host driver. 1-Enable, 0-Disable. * If the roaming is totally offloaded to the firmware, this request when * enabled shall mandate the firmware to notify all the relevant roam events * represented by the below attributes. If the host is in the suspend mode, * the behavior of the firmware to notify these events is guided by * QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_DEVICE_STATE, and if the request is to get * these events in the suspend state, the firmware is expected to wake up the * host before the respective events are notified. Please note that such a * request to get the events in the suspend state will have a definite power * implication. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE: flag attribute. Represents * that the roam events need to be notified in the suspend state too. By * default, these roam events are notified in the resume state. With this flag, * the roam events are notified in both resume and suspend states. * This attribute is used in the request from the userspace to the host driver. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE: u32, used in STA mode only. * Represents the different roam event types, signified by the enum * qca_wlan_vendor_roam_event_type. * Each bit of this attribute represents the different roam even types reported * through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON: u32, used in STA * mode only. This represents the roam trigger reason for the last roaming * attempted by the firmware. Each bit of this attribute represents the * different roam trigger reason code which are defined in enum * qca_vendor_roam_triggers. * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON: u32, used in * STA mode only. This represents the roam invoke fail reason for the last * failed roam invoke. Different roam invoke failure reason codes * are specified in enum qca_vendor_roam_invoke_fail_reasons. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO: Array of candidates info * for which the roam is attempted. Each entry is a nested attribute defined * by enum qca_wlan_vendor_attr_roam_events_candidate_info. * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE: u8 attribute. Represents * the scan state on which the roam events need to be notified. The values for * this attribute are referred from enum qca_wlan_vendor_roam_scan_state. * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. * * @QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST: Nested attribute of * u32 values. List of frequencies in MHz considered for a roam scan. * This is sent as an event through QCA_NL80211_VENDOR_SUBCMD_ROAM_EVENTS. */ enum qca_wlan_vendor_attr_roam_events { QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVALID = 0, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CONFIGURE = 1, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_SUSPEND_STATE = 2, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TYPE = 3, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_TRIGGER_REASON = 4, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_INVOKE_FAIL_REASON = 5, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_CANDIDATE_INFO = 6, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_STATE = 7, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_ROAM_SCAN_FREQ_LIST = 8, /* keep last */ QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX = QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_AFTER_LAST -1, }; #endif /* QCA_VENDOR_H */ diff --git a/contrib/wpa/src/common/sae.c b/contrib/wpa/src/common/sae.c index b768c22faa9d..c0f154e9134d 100644 --- a/contrib/wpa/src/common/sae.c +++ b/contrib/wpa/src/common/sae.c @@ -1,2352 +1,2361 @@ /* * Simultaneous authentication of equals * Copyright (c) 2012-2016, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" #include "common.h" #include "utils/const_time.h" #include "crypto/crypto.h" #include "crypto/sha256.h" #include "crypto/sha384.h" #include "crypto/sha512.h" #include "crypto/random.h" #include "crypto/dh_groups.h" #include "ieee802_11_defs.h" #include "dragonfly.h" #include "sae.h" int sae_set_group(struct sae_data *sae, int group) { struct sae_temporary_data *tmp; #ifdef CONFIG_TESTING_OPTIONS /* Allow all groups for testing purposes in non-production builds. */ #else /* CONFIG_TESTING_OPTIONS */ if (!dragonfly_suitable_group(group, 0)) { wpa_printf(MSG_DEBUG, "SAE: Reject unsuitable group %d", group); return -1; } #endif /* CONFIG_TESTING_OPTIONS */ sae_clear_data(sae); tmp = sae->tmp = os_zalloc(sizeof(*tmp)); if (tmp == NULL) return -1; /* First, check if this is an ECC group */ tmp->ec = crypto_ec_init(group); if (tmp->ec) { wpa_printf(MSG_DEBUG, "SAE: Selecting supported ECC group %d", group); sae->group = group; tmp->prime_len = crypto_ec_prime_len(tmp->ec); tmp->prime = crypto_ec_get_prime(tmp->ec); tmp->order_len = crypto_ec_order_len(tmp->ec); tmp->order = crypto_ec_get_order(tmp->ec); return 0; } /* Not an ECC group, check FFC */ tmp->dh = dh_groups_get(group); if (tmp->dh) { wpa_printf(MSG_DEBUG, "SAE: Selecting supported FFC group %d", group); sae->group = group; tmp->prime_len = tmp->dh->prime_len; if (tmp->prime_len > SAE_MAX_PRIME_LEN) { sae_clear_data(sae); return -1; } tmp->prime_buf = crypto_bignum_init_set(tmp->dh->prime, tmp->prime_len); if (tmp->prime_buf == NULL) { sae_clear_data(sae); return -1; } tmp->prime = tmp->prime_buf; tmp->order_len = tmp->dh->order_len; tmp->order_buf = crypto_bignum_init_set(tmp->dh->order, tmp->dh->order_len); if (tmp->order_buf == NULL) { sae_clear_data(sae); return -1; } tmp->order = tmp->order_buf; return 0; } /* Unsupported group */ wpa_printf(MSG_DEBUG, "SAE: Group %d not supported by the crypto library", group); return -1; } void sae_clear_temp_data(struct sae_data *sae) { struct sae_temporary_data *tmp; if (sae == NULL || sae->tmp == NULL) return; tmp = sae->tmp; crypto_ec_deinit(tmp->ec); crypto_bignum_deinit(tmp->prime_buf, 0); crypto_bignum_deinit(tmp->order_buf, 0); crypto_bignum_deinit(tmp->sae_rand, 1); crypto_bignum_deinit(tmp->pwe_ffc, 1); crypto_bignum_deinit(tmp->own_commit_scalar, 0); crypto_bignum_deinit(tmp->own_commit_element_ffc, 0); crypto_bignum_deinit(tmp->peer_commit_element_ffc, 0); crypto_ec_point_deinit(tmp->pwe_ecc, 1); crypto_ec_point_deinit(tmp->own_commit_element_ecc, 0); crypto_ec_point_deinit(tmp->peer_commit_element_ecc, 0); wpabuf_free(tmp->anti_clogging_token); wpabuf_free(tmp->own_rejected_groups); wpabuf_free(tmp->peer_rejected_groups); os_free(tmp->pw_id); bin_clear_free(tmp, sizeof(*tmp)); sae->tmp = NULL; } void sae_clear_data(struct sae_data *sae) { if (sae == NULL) return; sae_clear_temp_data(sae); crypto_bignum_deinit(sae->peer_commit_scalar, 0); crypto_bignum_deinit(sae->peer_commit_scalar_accepted, 0); os_memset(sae, 0, sizeof(*sae)); } static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key) { wpa_printf(MSG_DEBUG, "SAE: PWE derivation - addr1=" MACSTR " addr2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { os_memcpy(key, addr1, ETH_ALEN); os_memcpy(key + ETH_ALEN, addr2, ETH_ALEN); } else { os_memcpy(key, addr2, ETH_ALEN); os_memcpy(key + ETH_ALEN, addr1, ETH_ALEN); } } static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, const u8 *prime, const u8 *qr, const u8 *qnr, u8 *pwd_value) { struct crypto_bignum *y_sqr, *x_cand; int res; size_t bits; int cmp_prime; unsigned int in_range; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ bits = crypto_ec_prime_len_bits(sae->tmp->ec); if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", prime, sae->tmp->prime_len, pwd_value, bits) < 0) return -1; if (bits % 8) buf_shift_right(pwd_value, sae->tmp->prime_len, 8 - bits % 8); wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, sae->tmp->prime_len); cmp_prime = const_time_memcmp(pwd_value, prime, sae->tmp->prime_len); /* Create a const_time mask for selection based on prf result * being smaller than prime. */ in_range = const_time_fill_msb((unsigned int) cmp_prime); /* The algorithm description would skip the next steps if * cmp_prime >= 0 (return 0 here), but go through them regardless to * minimize externally observable differences in behavior. */ x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); if (!x_cand) return -1; y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand); crypto_bignum_deinit(x_cand, 1); if (!y_sqr) return -1; res = dragonfly_is_quadratic_residue_blind(sae->tmp->ec, qr, qnr, y_sqr); crypto_bignum_deinit(y_sqr, 1); if (res < 0) return res; return const_time_select_int(in_range, res, 0); } /* Returns -1 on fatal failure, 0 if PWE cannot be derived from the provided * pwd-seed, or 1 if a valid PWE was derived from pwd-seed. */ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed, struct crypto_bignum *pwe) { u8 pwd_value[SAE_MAX_PRIME_LEN]; size_t bits = sae->tmp->prime_len * 8; u8 exp[1]; struct crypto_bignum *a, *b = NULL; int res, is_val; u8 pwd_value_valid; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN); /* pwd-value = KDF-z(pwd-seed, "SAE Hunting and Pecking", p) */ if (sha256_prf_bits(pwd_seed, SHA256_MAC_LEN, "SAE Hunting and Pecking", sae->tmp->dh->prime, sae->tmp->prime_len, pwd_value, bits) < 0) return -1; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, sae->tmp->prime_len); /* Check whether pwd-value < p */ res = const_time_memcmp(pwd_value, sae->tmp->dh->prime, sae->tmp->prime_len); /* pwd-value >= p is invalid, so res is < 0 for the valid cases and * the negative sign can be used to fill the mask for constant time * selection */ pwd_value_valid = const_time_fill_msb(res); /* If pwd-value >= p, force pwd-value to be < p and perform the * calculations anyway to hide timing difference. The derived PWE will * be ignored in that case. */ pwd_value[0] = const_time_select_u8(pwd_value_valid, pwd_value[0], 0); /* PWE = pwd-value^((p-1)/r) modulo p */ res = -1; a = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); if (!a) goto fail; /* This is an optimization based on the used group that does not depend * on the password in any way, so it is fine to use separate branches * for this step without constant time operations. */ if (sae->tmp->dh->safe_prime) { /* * r = (p-1)/2 for the group used here, so this becomes: * PWE = pwd-value^2 modulo p */ exp[0] = 2; b = crypto_bignum_init_set(exp, sizeof(exp)); } else { /* Calculate exponent: (p-1)/r */ exp[0] = 1; b = crypto_bignum_init_set(exp, sizeof(exp)); if (b == NULL || crypto_bignum_sub(sae->tmp->prime, b, b) < 0 || crypto_bignum_div(b, sae->tmp->order, b) < 0) goto fail; } if (!b) goto fail; res = crypto_bignum_exptmod(a, b, sae->tmp->prime, pwe); if (res < 0) goto fail; /* There were no fatal errors in calculations, so determine the return * value using constant time operations. We get here for number of * invalid cases which are cleared here after having performed all the * computation. PWE is valid if pwd-value was less than prime and * PWE > 1. Start with pwd-value check first and then use constant time * operations to clear res to 0 if PWE is 0 or 1. */ res = const_time_select_u8(pwd_value_valid, 1, 0); is_val = crypto_bignum_is_zero(pwe); res = const_time_select_u8(const_time_is_zero(is_val), res, 0); is_val = crypto_bignum_is_one(pwe); res = const_time_select_u8(const_time_is_zero(is_val), res, 0); fail: crypto_bignum_deinit(a, 1); crypto_bignum_deinit(b, 1); return res; } static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1, const u8 *addr2, const u8 *password, size_t password_len) { u8 counter, k; u8 addrs[2 * ETH_ALEN]; const u8 *addr[2]; size_t len[2]; u8 *stub_password, *tmp_password; int pwd_seed_odd = 0; u8 prime[SAE_MAX_ECC_PRIME_LEN]; size_t prime_len; - struct crypto_bignum *x = NULL, *qr = NULL, *qnr = NULL; + struct crypto_bignum *x = NULL, *y = NULL, *qr = NULL, *qnr = NULL; u8 x_bin[SAE_MAX_ECC_PRIME_LEN]; u8 x_cand_bin[SAE_MAX_ECC_PRIME_LEN]; u8 qr_bin[SAE_MAX_ECC_PRIME_LEN]; u8 qnr_bin[SAE_MAX_ECC_PRIME_LEN]; + u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; int res = -1; u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* * mask */ + unsigned int is_eq; os_memset(x_bin, 0, sizeof(x_bin)); stub_password = os_malloc(password_len); tmp_password = os_malloc(password_len); if (!stub_password || !tmp_password || random_get_bytes(stub_password, password_len) < 0) goto fail; prime_len = sae->tmp->prime_len; if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), prime_len) < 0) goto fail; /* * Create a random quadratic residue (qr) and quadratic non-residue * (qnr) modulo p for blinding purposes during the loop. */ if (dragonfly_get_random_qr_qnr(sae->tmp->prime, &qr, &qnr) < 0 || crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), prime_len) < 0 || crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), prime_len) < 0) goto fail; wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", password, password_len); /* * H(salt, ikm) = HMAC-SHA256(salt, ikm) * base = password * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), * base || counter) */ sae_pwd_seed_key(addr1, addr2, addrs); addr[0] = tmp_password; len[0] = password_len; addr[1] = &counter; len[1] = sizeof(counter); /* * Continue for at least k iterations to protect against side-channel * attacks that attempt to determine the number of iterations required * in the loop. */ k = dragonfly_min_pwe_loop_iter(sae->group); for (counter = 1; counter <= k || !found; counter++) { u8 pwd_seed[SHA256_MAC_LEN]; if (counter > 200) { /* This should not happen in practice */ wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); break; } wpa_printf(MSG_DEBUG, "SAE: counter = %03u", counter); const_time_select_bin(found, stub_password, password, password_len, tmp_password); if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len, pwd_seed) < 0) break; res = sae_test_pwd_seed_ecc(sae, pwd_seed, prime, qr_bin, qnr_bin, x_cand_bin); const_time_select_bin(found, x_bin, x_cand_bin, prime_len, x_bin); pwd_seed_odd = const_time_select_u8( found, pwd_seed_odd, pwd_seed[SHA256_MAC_LEN - 1] & 0x01); os_memset(pwd_seed, 0, sizeof(pwd_seed)); if (res < 0) goto fail; /* Need to minimize differences in handling res == 0 and 1 here * to avoid differences in timing and instruction cache access, * so use const_time_select_*() to make local copies of the * values based on whether this loop iteration was the one that * found the pwd-seed/x. */ /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them * (with res converted to 0/0xff) handles this in constant time. */ found |= res * 0xff; wpa_printf(MSG_DEBUG, "SAE: pwd-seed result %d found=0x%02x", res, found); } if (!found) { wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); res = -1; goto fail; } x = crypto_bignum_init_set(x_bin, prime_len); if (!x) { res = -1; goto fail; } - if (!sae->tmp->pwe_ecc) - sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec); - if (!sae->tmp->pwe_ecc) - res = -1; - else - res = crypto_ec_point_solve_y_coord(sae->tmp->ec, - sae->tmp->pwe_ecc, x, - pwd_seed_odd); - if (res < 0) { - /* - * This should not happen since we already checked that there - * is a result. - */ + /* y = sqrt(x^3 + ax + b) mod p + * if LSB(save) == LSB(y): PWE = (x, y) + * else: PWE = (x, p - y) + * + * Calculate y and the two possible values for PWE and after that, + * use constant time selection to copy the correct alternative. + */ + y = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x); + if (!y || + dragonfly_sqrt(sae->tmp->ec, y, y) < 0 || + crypto_bignum_to_bin(y, x_y, SAE_MAX_ECC_PRIME_LEN, + prime_len) < 0 || + crypto_bignum_sub(sae->tmp->prime, y, y) < 0 || + crypto_bignum_to_bin(y, x_y + SAE_MAX_ECC_PRIME_LEN, + SAE_MAX_ECC_PRIME_LEN, prime_len) < 0) { wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); + goto fail; + } + + is_eq = const_time_eq(pwd_seed_odd, x_y[prime_len - 1] & 0x01); + const_time_select_bin(is_eq, x_y, x_y + SAE_MAX_ECC_PRIME_LEN, + prime_len, x_y + prime_len); + os_memcpy(x_y, x_bin, prime_len); + wpa_hexdump_key(MSG_DEBUG, "SAE: PWE", x_y, 2 * prime_len); + crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); + sae->tmp->pwe_ecc = crypto_ec_point_from_bin(sae->tmp->ec, x_y); + if (!sae->tmp->pwe_ecc) { + wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE"); + res = -1; } fail: + forced_memzero(x_y, sizeof(x_y)); crypto_bignum_deinit(qr, 0); crypto_bignum_deinit(qnr, 0); + crypto_bignum_deinit(y, 1); os_free(stub_password); bin_clear_free(tmp_password, password_len); crypto_bignum_deinit(x, 1); os_memset(x_bin, 0, sizeof(x_bin)); os_memset(x_cand_bin, 0, sizeof(x_cand_bin)); return res; } static int sae_derive_pwe_ffc(struct sae_data *sae, const u8 *addr1, const u8 *addr2, const u8 *password, size_t password_len) { u8 counter, k, sel_counter = 0; u8 addrs[2 * ETH_ALEN]; const u8 *addr[2]; size_t len[2]; u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* * mask */ u8 mask; struct crypto_bignum *pwe; size_t prime_len = sae->tmp->prime_len * 8; u8 *pwe_buf; crypto_bignum_deinit(sae->tmp->pwe_ffc, 1); sae->tmp->pwe_ffc = NULL; /* Allocate a buffer to maintain selected and candidate PWE for constant * time selection. */ pwe_buf = os_zalloc(prime_len * 2); pwe = crypto_bignum_init(); if (!pwe_buf || !pwe) goto fail; wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", password, password_len); /* * H(salt, ikm) = HMAC-SHA256(salt, ikm) * pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), * password || counter) */ sae_pwd_seed_key(addr1, addr2, addrs); addr[0] = password; len[0] = password_len; addr[1] = &counter; len[1] = sizeof(counter); k = dragonfly_min_pwe_loop_iter(sae->group); for (counter = 1; counter <= k || !found; counter++) { u8 pwd_seed[SHA256_MAC_LEN]; int res; if (counter > 200) { /* This should not happen in practice */ wpa_printf(MSG_DEBUG, "SAE: Failed to derive PWE"); break; } wpa_printf(MSG_DEBUG, "SAE: counter = %02u", counter); if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len, pwd_seed) < 0) break; res = sae_test_pwd_seed_ffc(sae, pwd_seed, pwe); /* res is -1 for fatal failure, 0 if a valid PWE was not found, * or 1 if a valid PWE was found. */ if (res < 0) break; /* Store the candidate PWE into the second half of pwe_buf and * the selected PWE in the beginning of pwe_buf using constant * time selection. */ if (crypto_bignum_to_bin(pwe, pwe_buf + prime_len, prime_len, prime_len) < 0) break; const_time_select_bin(found, pwe_buf, pwe_buf + prime_len, prime_len, pwe_buf); sel_counter = const_time_select_u8(found, sel_counter, counter); mask = const_time_eq_u8(res, 1); found = const_time_select_u8(found, found, mask); } if (!found) goto fail; wpa_printf(MSG_DEBUG, "SAE: Use PWE from counter = %02u", sel_counter); sae->tmp->pwe_ffc = crypto_bignum_init_set(pwe_buf, prime_len); fail: crypto_bignum_deinit(pwe, 1); bin_clear_free(pwe_buf, prime_len * 2); return sae->tmp->pwe_ffc ? 0 : -1; } static int hkdf_extract(size_t hash_len, const u8 *salt, size_t salt_len, size_t num_elem, const u8 *addr[], const size_t len[], u8 *prk) { if (hash_len == 32) return hmac_sha256_vector(salt, salt_len, num_elem, addr, len, prk); #ifdef CONFIG_SHA384 if (hash_len == 48) return hmac_sha384_vector(salt, salt_len, num_elem, addr, len, prk); #endif /* CONFIG_SHA384 */ #ifdef CONFIG_SHA512 if (hash_len == 64) return hmac_sha512_vector(salt, salt_len, num_elem, addr, len, prk); #endif /* CONFIG_SHA512 */ return -1; } static int hkdf_expand(size_t hash_len, const u8 *prk, size_t prk_len, const char *info, u8 *okm, size_t okm_len) { size_t info_len = os_strlen(info); if (hash_len == 32) return hmac_sha256_kdf(prk, prk_len, NULL, (const u8 *) info, info_len, okm, okm_len); #ifdef CONFIG_SHA384 if (hash_len == 48) return hmac_sha384_kdf(prk, prk_len, NULL, (const u8 *) info, info_len, okm, okm_len); #endif /* CONFIG_SHA384 */ #ifdef CONFIG_SHA512 if (hash_len == 64) return hmac_sha512_kdf(prk, prk_len, NULL, (const u8 *) info, info_len, okm, okm_len); #endif /* CONFIG_SHA512 */ return -1; } static int sswu_curve_param(int group, int *z) { switch (group) { case 19: *z = -10; return 0; case 20: *z = -12; return 0; case 21: *z = -4; return 0; case 25: case 29: *z = -5; return 0; case 26: *z = 31; return 0; case 28: *z = -2; return 0; case 30: *z = 7; return 0; } return -1; } static void debug_print_bignum(const char *title, const struct crypto_bignum *a, size_t prime_len) { u8 *bin; bin = os_malloc(prime_len); if (bin && crypto_bignum_to_bin(a, bin, prime_len, prime_len) >= 0) wpa_hexdump_key(MSG_DEBUG, title, bin, prime_len); else wpa_printf(MSG_DEBUG, "Could not print bignum (%s)", title); bin_clear_free(bin, prime_len); } static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, const struct crypto_bignum *u) { int z_int; const struct crypto_bignum *a, *b, *prime; struct crypto_bignum *u2, *t1, *t2, *z, *t, *zero, *one, *two, *three, *x1a, *x1b, *y = NULL; struct crypto_bignum *x1 = NULL, *x2, *gx1, *gx2, *v = NULL; unsigned int m_is_zero, is_qr, is_eq; size_t prime_len; u8 bin[SAE_MAX_ECC_PRIME_LEN]; u8 bin1[SAE_MAX_ECC_PRIME_LEN]; u8 bin2[SAE_MAX_ECC_PRIME_LEN]; u8 x_y[2 * SAE_MAX_ECC_PRIME_LEN]; struct crypto_ec_point *p = NULL; if (sswu_curve_param(group, &z_int) < 0) return NULL; prime = crypto_ec_get_prime(ec); prime_len = crypto_ec_prime_len(ec); a = crypto_ec_get_a(ec); b = crypto_ec_get_b(ec); u2 = crypto_bignum_init(); t1 = crypto_bignum_init(); t2 = crypto_bignum_init(); z = crypto_bignum_init_uint(abs(z_int)); t = crypto_bignum_init(); zero = crypto_bignum_init_uint(0); one = crypto_bignum_init_uint(1); two = crypto_bignum_init_uint(2); three = crypto_bignum_init_uint(3); x1a = crypto_bignum_init(); x1b = crypto_bignum_init(); x2 = crypto_bignum_init(); gx1 = crypto_bignum_init(); gx2 = crypto_bignum_init(); if (!u2 || !t1 || !t2 || !z || !t || !zero || !one || !two || !three || !x1a || !x1b || !x2 || !gx1 || !gx2) goto fail; if (z_int < 0 && crypto_bignum_sub(prime, z, z) < 0) goto fail; /* m = z^2 * u^4 + z * u^2 */ /* --> tmp = z * u^2, m = tmp^2 + tmp */ /* u2 = u^2 * t1 = z * u2 * t2 = t1^2 * m = t1 = t1 + t2 */ if (crypto_bignum_sqrmod(u, prime, u2) < 0 || crypto_bignum_mulmod(z, u2, prime, t1) < 0 || crypto_bignum_sqrmod(t1, prime, t2) < 0 || crypto_bignum_addmod(t1, t2, prime, t1) < 0) goto fail; debug_print_bignum("SSWU: m", t1, prime_len); /* l = CEQ(m, 0) * t = CSEL(l, 0, inverse(m); where inverse(x) is calculated as * x^(p-2) modulo p which will handle m == 0 case correctly */ /* TODO: Make sure crypto_bignum_is_zero() is constant time */ m_is_zero = const_time_eq(crypto_bignum_is_zero(t1), 1); /* t = m^(p-2) modulo p */ if (crypto_bignum_sub(prime, two, t2) < 0 || crypto_bignum_exptmod(t1, t2, prime, t) < 0) goto fail; debug_print_bignum("SSWU: t", t, prime_len); /* b / (z * a) */ if (crypto_bignum_mulmod(z, a, prime, t1) < 0 || crypto_bignum_inverse(t1, prime, t1) < 0 || crypto_bignum_mulmod(b, t1, prime, x1a) < 0) goto fail; debug_print_bignum("SSWU: x1a = b / (z * a)", x1a, prime_len); /* (-b/a) * (1 + t) */ if (crypto_bignum_sub(prime, b, t1) < 0 || crypto_bignum_inverse(a, prime, t2) < 0 || crypto_bignum_mulmod(t1, t2, prime, t1) < 0 || crypto_bignum_addmod(one, t, prime, t2) < 0 || crypto_bignum_mulmod(t1, t2, prime, x1b) < 0) goto fail; debug_print_bignum("SSWU: x1b = (-b/a) * (1 + t)", x1b, prime_len); /* x1 = CSEL(CEQ(m, 0), x1a, x1b) */ if (crypto_bignum_to_bin(x1a, bin1, sizeof(bin1), prime_len) < 0 || crypto_bignum_to_bin(x1b, bin2, sizeof(bin2), prime_len) < 0) goto fail; const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin); x1 = crypto_bignum_init_set(bin, prime_len); if (!x1) goto fail; debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len); /* gx1 = x1^3 + a * x1 + b */ if (crypto_bignum_exptmod(x1, three, prime, t1) < 0 || crypto_bignum_mulmod(a, x1, prime, t2) < 0 || crypto_bignum_addmod(t1, t2, prime, t1) < 0 || crypto_bignum_addmod(t1, b, prime, gx1) < 0) goto fail; debug_print_bignum("SSWU: gx1 = x1^3 + a * x1 + b", gx1, prime_len); /* x2 = z * u^2 * x1 */ if (crypto_bignum_mulmod(z, u2, prime, t1) < 0 || crypto_bignum_mulmod(t1, x1, prime, x2) < 0) goto fail; debug_print_bignum("SSWU: x2 = z * u^2 * x1", x2, prime_len); /* gx2 = x2^3 + a * x2 + b */ if (crypto_bignum_exptmod(x2, three, prime, t1) < 0 || crypto_bignum_mulmod(a, x2, prime, t2) < 0 || crypto_bignum_addmod(t1, t2, prime, t1) < 0 || crypto_bignum_addmod(t1, b, prime, gx2) < 0) goto fail; debug_print_bignum("SSWU: gx2 = x2^3 + a * x2 + b", gx2, prime_len); /* l = gx1 is a quadratic residue modulo p * --> gx1^((p-1)/2) modulo p is zero or one */ if (crypto_bignum_sub(prime, one, t1) < 0 || crypto_bignum_rshift(t1, 1, t1) < 0 || crypto_bignum_exptmod(gx1, t1, prime, t1) < 0) goto fail; debug_print_bignum("SSWU: gx1^((p-1)/2) modulo p", t1, prime_len); is_qr = const_time_eq(crypto_bignum_is_zero(t1) | crypto_bignum_is_one(t1), 1); /* v = CSEL(l, gx1, gx2) */ if (crypto_bignum_to_bin(gx1, bin1, sizeof(bin1), prime_len) < 0 || crypto_bignum_to_bin(gx2, bin2, sizeof(bin2), prime_len) < 0) goto fail; const_time_select_bin(is_qr, bin1, bin2, prime_len, bin); v = crypto_bignum_init_set(bin, prime_len); if (!v) goto fail; debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len); /* x = CSEL(l, x1, x2) */ if (crypto_bignum_to_bin(x1, bin1, sizeof(bin1), prime_len) < 0 || crypto_bignum_to_bin(x2, bin2, sizeof(bin2), prime_len) < 0) goto fail; const_time_select_bin(is_qr, bin1, bin2, prime_len, x_y); wpa_hexdump_key(MSG_DEBUG, "SSWU: x = CSEL(l, x1, x2)", x_y, prime_len); - /* y = sqrt(v) - * For prime p such that p = 3 mod 4 --> v^((p+1)/4) */ - if (crypto_bignum_to_bin(prime, bin1, sizeof(bin1), prime_len) < 0) - goto fail; - if ((bin1[prime_len - 1] & 0x03) != 3) { - wpa_printf(MSG_DEBUG, "SSWU: prime does not have p = 3 mod 4"); - goto fail; - } + /* y = sqrt(v) */ y = crypto_bignum_init(); - if (!y || - crypto_bignum_add(prime, one, t1) < 0 || - crypto_bignum_rshift(t1, 2, t1) < 0 || - crypto_bignum_exptmod(v, t1, prime, y) < 0) + if (!y || dragonfly_sqrt(ec, v, y) < 0) goto fail; debug_print_bignum("SSWU: y = sqrt(v)", y, prime_len); /* l = CEQ(LSB(u), LSB(y)) */ if (crypto_bignum_to_bin(u, bin1, sizeof(bin1), prime_len) < 0 || crypto_bignum_to_bin(y, bin2, sizeof(bin2), prime_len) < 0) goto fail; is_eq = const_time_eq(bin1[prime_len - 1] & 0x01, bin2[prime_len - 1] & 0x01); /* P = CSEL(l, (x,y), (x, p-y)) */ if (crypto_bignum_sub(prime, y, t1) < 0) goto fail; debug_print_bignum("SSWU: p - y", t1, prime_len); if (crypto_bignum_to_bin(y, bin1, sizeof(bin1), prime_len) < 0 || crypto_bignum_to_bin(t1, bin2, sizeof(bin2), prime_len) < 0) goto fail; const_time_select_bin(is_eq, bin1, bin2, prime_len, &x_y[prime_len]); /* output P */ wpa_hexdump_key(MSG_DEBUG, "SSWU: P.x", x_y, prime_len); wpa_hexdump_key(MSG_DEBUG, "SSWU: P.y", &x_y[prime_len], prime_len); p = crypto_ec_point_from_bin(ec, x_y); fail: crypto_bignum_deinit(u2, 1); crypto_bignum_deinit(t1, 1); crypto_bignum_deinit(t2, 1); crypto_bignum_deinit(z, 0); crypto_bignum_deinit(t, 1); crypto_bignum_deinit(x1a, 1); crypto_bignum_deinit(x1b, 1); crypto_bignum_deinit(x1, 1); crypto_bignum_deinit(x2, 1); crypto_bignum_deinit(gx1, 1); crypto_bignum_deinit(gx2, 1); crypto_bignum_deinit(y, 1); crypto_bignum_deinit(v, 1); crypto_bignum_deinit(zero, 0); crypto_bignum_deinit(one, 0); crypto_bignum_deinit(two, 0); crypto_bignum_deinit(three, 0); forced_memzero(bin, sizeof(bin)); forced_memzero(bin1, sizeof(bin1)); forced_memzero(bin2, sizeof(bin2)); forced_memzero(x_y, sizeof(x_y)); return p; } static int sae_pwd_seed(size_t hash_len, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier, u8 *pwd_seed) { const u8 *addr[2]; size_t len[2]; size_t num_elem; /* pwd-seed = HKDF-Extract(ssid, password [ || identifier ]) */ addr[0] = password; len[0] = password_len; num_elem = 1; wpa_hexdump_ascii(MSG_DEBUG, "SAE: SSID", ssid, ssid_len); wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password", password, password_len); if (identifier) { wpa_printf(MSG_DEBUG, "SAE: password identifier: %s", identifier); addr[num_elem] = (const u8 *) identifier; len[num_elem] = os_strlen(identifier); num_elem++; } if (hkdf_extract(hash_len, ssid, ssid_len, num_elem, addr, len, pwd_seed) < 0) return -1; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, hash_len); return 0; } size_t sae_ecc_prime_len_2_hash_len(size_t prime_len) { if (prime_len <= 256 / 8) return 32; if (prime_len <= 384 / 8) return 48; return 64; } static struct crypto_ec_point * sae_derive_pt_ecc(struct crypto_ec *ec, int group, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier) { u8 pwd_seed[64]; u8 pwd_value[SAE_MAX_ECC_PRIME_LEN * 2]; size_t pwd_value_len, hash_len, prime_len; const struct crypto_bignum *prime; struct crypto_bignum *bn = NULL; struct crypto_ec_point *p1 = NULL, *p2 = NULL, *pt = NULL; prime = crypto_ec_get_prime(ec); prime_len = crypto_ec_prime_len(ec); if (prime_len > SAE_MAX_ECC_PRIME_LEN) goto fail; hash_len = sae_ecc_prime_len_2_hash_len(prime_len); /* len = olen(p) + ceil(olen(p)/2) */ pwd_value_len = prime_len + (prime_len + 1) / 2; if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len, identifier, pwd_seed) < 0) goto fail; /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u1 P1", len) */ if (hkdf_expand(hash_len, pwd_seed, hash_len, "SAE Hash to Element u1 P1", pwd_value, pwd_value_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u1 P1)", pwd_value, pwd_value_len); /* u1 = pwd-value modulo p */ bn = crypto_bignum_init_set(pwd_value, pwd_value_len); if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 || crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value), prime_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: u1", pwd_value, prime_len); /* P1 = SSWU(u1) */ p1 = sswu(ec, group, bn); if (!p1) goto fail; /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element u2 P2", len) */ if (hkdf_expand(hash_len, pwd_seed, hash_len, "SAE Hash to Element u2 P2", pwd_value, pwd_value_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value (u2 P2)", pwd_value, pwd_value_len); /* u2 = pwd-value modulo p */ crypto_bignum_deinit(bn, 1); bn = crypto_bignum_init_set(pwd_value, pwd_value_len); if (!bn || crypto_bignum_mod(bn, prime, bn) < 0 || crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value), prime_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: u2", pwd_value, prime_len); /* P2 = SSWU(u2) */ p2 = sswu(ec, group, bn); if (!p2) goto fail; /* PT = elem-op(P1, P2) */ pt = crypto_ec_point_init(ec); if (!pt) goto fail; if (crypto_ec_point_add(ec, p1, p2, pt) < 0) { crypto_ec_point_deinit(pt, 1); pt = NULL; } fail: forced_memzero(pwd_seed, sizeof(pwd_seed)); forced_memzero(pwd_value, sizeof(pwd_value)); crypto_bignum_deinit(bn, 1); crypto_ec_point_deinit(p1, 1); crypto_ec_point_deinit(p2, 1); return pt; } size_t sae_ffc_prime_len_2_hash_len(size_t prime_len) { if (prime_len <= 2048 / 8) return 32; if (prime_len <= 3072 / 8) return 48; return 64; } static struct crypto_bignum * sae_derive_pt_ffc(const struct dh_group *dh, int group, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier) { size_t hash_len, prime_len, pwd_value_len; struct crypto_bignum *prime, *order; struct crypto_bignum *one = NULL, *two = NULL, *bn = NULL, *tmp = NULL, *pt = NULL; u8 pwd_seed[64]; u8 pwd_value[SAE_MAX_PRIME_LEN + SAE_MAX_PRIME_LEN / 2]; prime = crypto_bignum_init_set(dh->prime, dh->prime_len); order = crypto_bignum_init_set(dh->order, dh->order_len); if (!prime || !order) goto fail; prime_len = dh->prime_len; if (prime_len > SAE_MAX_PRIME_LEN) goto fail; hash_len = sae_ffc_prime_len_2_hash_len(prime_len); /* len = olen(p) + ceil(olen(p)/2) */ pwd_value_len = prime_len + (prime_len + 1) / 2; if (pwd_value_len > sizeof(pwd_value)) goto fail; if (sae_pwd_seed(hash_len, ssid, ssid_len, password, password_len, identifier, pwd_seed) < 0) goto fail; /* pwd-value = HKDF-Expand(pwd-seed, "SAE Hash to Element", len) */ if (hkdf_expand(hash_len, pwd_seed, hash_len, "SAE Hash to Element", pwd_value, pwd_value_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value", pwd_value, pwd_value_len); /* pwd-value = (pwd-value modulo (p-2)) + 2 */ bn = crypto_bignum_init_set(pwd_value, pwd_value_len); one = crypto_bignum_init_uint(1); two = crypto_bignum_init_uint(2); tmp = crypto_bignum_init(); if (!bn || !one || !two || !tmp || crypto_bignum_sub(prime, two, tmp) < 0 || crypto_bignum_mod(bn, tmp, bn) < 0 || crypto_bignum_add(bn, two, bn) < 0 || crypto_bignum_to_bin(bn, pwd_value, sizeof(pwd_value), prime_len) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-value(reduced)", pwd_value, prime_len); /* PT = pwd-value^((p-1)/q) modulo p */ pt = crypto_bignum_init(); if (!pt || crypto_bignum_sub(prime, one, tmp) < 0 || crypto_bignum_div(tmp, order, tmp) < 0 || crypto_bignum_exptmod(bn, tmp, prime, pt) < 0) { crypto_bignum_deinit(pt, 1); pt = NULL; goto fail; } debug_print_bignum("SAE: PT", pt, prime_len); fail: forced_memzero(pwd_seed, sizeof(pwd_seed)); forced_memzero(pwd_value, sizeof(pwd_value)); crypto_bignum_deinit(bn, 1); crypto_bignum_deinit(tmp, 1); crypto_bignum_deinit(one, 0); crypto_bignum_deinit(two, 0); crypto_bignum_deinit(prime, 0); crypto_bignum_deinit(order, 0); return pt; } static struct sae_pt * sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier) { struct sae_pt *pt; wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group); if (ssid_len > 32) return NULL; pt = os_zalloc(sizeof(*pt)); if (!pt) return NULL; #ifdef CONFIG_SAE_PK os_memcpy(pt->ssid, ssid, ssid_len); pt->ssid_len = ssid_len; #endif /* CONFIG_SAE_PK */ pt->group = group; pt->ec = crypto_ec_init(group); if (pt->ec) { pt->ecc_pt = sae_derive_pt_ecc(pt->ec, group, ssid, ssid_len, password, password_len, identifier); if (!pt->ecc_pt) { wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT"); goto fail; } return pt; } pt->dh = dh_groups_get(group); if (!pt->dh) { wpa_printf(MSG_DEBUG, "SAE: Unsupported group %d", group); goto fail; } pt->ffc_pt = sae_derive_pt_ffc(pt->dh, group, ssid, ssid_len, password, password_len, identifier); if (!pt->ffc_pt) { wpa_printf(MSG_DEBUG, "SAE: Failed to derive PT"); goto fail; } return pt; fail: sae_deinit_pt(pt); return NULL; } struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier) { struct sae_pt *pt = NULL, *last = NULL, *tmp; int default_groups[] = { 19, 0 }; int i; if (!groups) groups = default_groups; for (i = 0; groups[i] > 0; i++) { tmp = sae_derive_pt_group(groups[i], ssid, ssid_len, password, password_len, identifier); if (!tmp) continue; if (last) last->next = tmp; else pt = tmp; last = tmp; } return pt; } static void sae_max_min_addr(const u8 *addr[], size_t len[], const u8 *addr1, const u8 *addr2) { len[0] = ETH_ALEN; len[1] = ETH_ALEN; if (os_memcmp(addr1, addr2, ETH_ALEN) > 0) { addr[0] = addr1; addr[1] = addr2; } else { addr[0] = addr2; addr[1] = addr1; } } struct crypto_ec_point * sae_derive_pwe_from_pt_ecc(const struct sae_pt *pt, const u8 *addr1, const u8 *addr2) { u8 bin[SAE_MAX_ECC_PRIME_LEN * 2]; size_t prime_len; const u8 *addr[2]; size_t len[2]; u8 salt[64], hash[64]; size_t hash_len; const struct crypto_bignum *order; struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL; struct crypto_ec_point *pwe = NULL; wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT"); prime_len = crypto_ec_prime_len(pt->ec); if (crypto_ec_point_to_bin(pt->ec, pt->ecc_pt, bin, bin + prime_len) < 0) return NULL; wpa_hexdump_key(MSG_DEBUG, "SAE: PT.x", bin, prime_len); wpa_hexdump_key(MSG_DEBUG, "SAE: PT.y", bin + prime_len, prime_len); sae_max_min_addr(addr, len, addr1, addr2); /* val = H(0^n, * MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */ wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))"); hash_len = sae_ecc_prime_len_2_hash_len(prime_len); os_memset(salt, 0, hash_len); if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0) goto fail; wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len); /* val = val modulo (q - 1) + 1 */ order = crypto_ec_get_order(pt->ec); tmp = crypto_bignum_init(); val = crypto_bignum_init_set(hash, hash_len); one = crypto_bignum_init_uint(1); if (!tmp || !val || !one || crypto_bignum_sub(order, one, tmp) < 0 || crypto_bignum_mod(val, tmp, val) < 0 || crypto_bignum_add(val, one, val) < 0) goto fail; debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len); /* PWE = scalar-op(val, PT) */ pwe = crypto_ec_point_init(pt->ec); if (!pwe || crypto_ec_point_mul(pt->ec, pt->ecc_pt, val, pwe) < 0 || crypto_ec_point_to_bin(pt->ec, pwe, bin, bin + prime_len) < 0) { crypto_ec_point_deinit(pwe, 1); pwe = NULL; goto fail; } wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.x", bin, prime_len); wpa_hexdump_key(MSG_DEBUG, "SAE: PWE.y", bin + prime_len, prime_len); fail: crypto_bignum_deinit(tmp, 1); crypto_bignum_deinit(val, 1); crypto_bignum_deinit(one, 0); return pwe; } struct crypto_bignum * sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt, const u8 *addr1, const u8 *addr2) { size_t prime_len; const u8 *addr[2]; size_t len[2]; u8 salt[64], hash[64]; size_t hash_len; struct crypto_bignum *tmp = NULL, *val = NULL, *one = NULL; struct crypto_bignum *pwe = NULL, *order = NULL, *prime = NULL; wpa_printf(MSG_DEBUG, "SAE: Derive PWE from PT"); prime = crypto_bignum_init_set(pt->dh->prime, pt->dh->prime_len); order = crypto_bignum_init_set(pt->dh->order, pt->dh->order_len); if (!prime || !order) goto fail; prime_len = pt->dh->prime_len; sae_max_min_addr(addr, len, addr1, addr2); /* val = H(0^n, * MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC)) */ wpa_printf(MSG_DEBUG, "SAE: val = H(0^n, MAX(addrs) || MIN(addrs))"); hash_len = sae_ffc_prime_len_2_hash_len(prime_len); os_memset(salt, 0, hash_len); if (hkdf_extract(hash_len, salt, hash_len, 2, addr, len, hash) < 0) goto fail; wpa_hexdump(MSG_DEBUG, "SAE: val", hash, hash_len); /* val = val modulo (q - 1) + 1 */ tmp = crypto_bignum_init(); val = crypto_bignum_init_set(hash, hash_len); one = crypto_bignum_init_uint(1); if (!tmp || !val || !one || crypto_bignum_sub(order, one, tmp) < 0 || crypto_bignum_mod(val, tmp, val) < 0 || crypto_bignum_add(val, one, val) < 0) goto fail; debug_print_bignum("SAE: val(reduced to 1..q-1)", val, prime_len); /* PWE = scalar-op(val, PT) */ pwe = crypto_bignum_init(); if (!pwe || crypto_bignum_exptmod(pt->ffc_pt, val, prime, pwe) < 0) { crypto_bignum_deinit(pwe, 1); pwe = NULL; goto fail; } debug_print_bignum("SAE: PWE", pwe, prime_len); fail: crypto_bignum_deinit(tmp, 1); crypto_bignum_deinit(val, 1); crypto_bignum_deinit(one, 0); crypto_bignum_deinit(prime, 0); crypto_bignum_deinit(order, 0); return pwe; } void sae_deinit_pt(struct sae_pt *pt) { struct sae_pt *prev; while (pt) { crypto_ec_point_deinit(pt->ecc_pt, 1); crypto_bignum_deinit(pt->ffc_pt, 1); crypto_ec_deinit(pt->ec); prev = pt; pt = pt->next; os_free(prev); } } static int sae_derive_commit_element_ecc(struct sae_data *sae, struct crypto_bignum *mask) { /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ if (!sae->tmp->own_commit_element_ecc) { sae->tmp->own_commit_element_ecc = crypto_ec_point_init(sae->tmp->ec); if (!sae->tmp->own_commit_element_ecc) return -1; } if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, mask, sae->tmp->own_commit_element_ecc) < 0 || crypto_ec_point_invert(sae->tmp->ec, sae->tmp->own_commit_element_ecc) < 0) { wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); return -1; } return 0; } static int sae_derive_commit_element_ffc(struct sae_data *sae, struct crypto_bignum *mask) { /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ if (!sae->tmp->own_commit_element_ffc) { sae->tmp->own_commit_element_ffc = crypto_bignum_init(); if (!sae->tmp->own_commit_element_ffc) return -1; } if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, mask, sae->tmp->prime, sae->tmp->own_commit_element_ffc) < 0 || crypto_bignum_inverse(sae->tmp->own_commit_element_ffc, sae->tmp->prime, sae->tmp->own_commit_element_ffc) < 0) { wpa_printf(MSG_DEBUG, "SAE: Could not compute commit-element"); return -1; } return 0; } static int sae_derive_commit(struct sae_data *sae) { struct crypto_bignum *mask; int ret; mask = crypto_bignum_init(); if (!sae->tmp->sae_rand) sae->tmp->sae_rand = crypto_bignum_init(); if (!sae->tmp->own_commit_scalar) sae->tmp->own_commit_scalar = crypto_bignum_init(); ret = !mask || !sae->tmp->sae_rand || !sae->tmp->own_commit_scalar || dragonfly_generate_scalar(sae->tmp->order, sae->tmp->sae_rand, mask, sae->tmp->own_commit_scalar) < 0 || (sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0) || (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0); crypto_bignum_deinit(mask, 1); return ret ? -1 : 0; } int sae_prepare_commit(const u8 *addr1, const u8 *addr2, const u8 *password, size_t password_len, struct sae_data *sae) { if (sae->tmp == NULL || (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password, password_len) < 0) || (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password, password_len) < 0)) return -1; sae->h2e = 0; sae->pk = 0; return sae_derive_commit(sae); } int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, const u8 *addr1, const u8 *addr2, int *rejected_groups, const struct sae_pk *pk) { if (!sae->tmp) return -1; while (pt) { if (pt->group == sae->group) break; pt = pt->next; } if (!pt) { wpa_printf(MSG_INFO, "SAE: Could not find PT for group %u", sae->group); return -1; } #ifdef CONFIG_SAE_PK os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len); sae->tmp->ssid_len = pt->ssid_len; sae->tmp->ap_pk = pk; #endif /* CONFIG_SAE_PK */ sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0; wpabuf_free(sae->tmp->own_rejected_groups); sae->tmp->own_rejected_groups = NULL; if (rejected_groups) { int count, i; struct wpabuf *groups; count = int_array_len(rejected_groups); groups = wpabuf_alloc(count * 2); if (!groups) return -1; for (i = 0; i < count; i++) wpabuf_put_le16(groups, rejected_groups[i]); sae->tmp->own_rejected_groups = groups; } if (pt->ec) { crypto_ec_point_deinit(sae->tmp->pwe_ecc, 1); sae->tmp->pwe_ecc = sae_derive_pwe_from_pt_ecc(pt, addr1, addr2); if (!sae->tmp->pwe_ecc) return -1; } if (pt->dh) { crypto_bignum_deinit(sae->tmp->pwe_ffc, 1); sae->tmp->pwe_ffc = sae_derive_pwe_from_pt_ffc(pt, addr1, addr2); if (!sae->tmp->pwe_ffc) return -1; } sae->h2e = 1; return sae_derive_commit(sae); } static int sae_derive_k_ecc(struct sae_data *sae, u8 *k) { struct crypto_ec_point *K; int ret = -1; K = crypto_ec_point_init(sae->tmp->ec); if (K == NULL) goto fail; /* * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), * PEER-COMMIT-ELEMENT))) * If K is identity element (point-at-infinity), reject * k = F(K) (= x coordinate) */ if (crypto_ec_point_mul(sae->tmp->ec, sae->tmp->pwe_ecc, sae->peer_commit_scalar, K) < 0 || crypto_ec_point_add(sae->tmp->ec, K, sae->tmp->peer_commit_element_ecc, K) < 0 || crypto_ec_point_mul(sae->tmp->ec, K, sae->tmp->sae_rand, K) < 0 || crypto_ec_point_is_at_infinity(sae->tmp->ec, K) || crypto_ec_point_to_bin(sae->tmp->ec, K, k, NULL) < 0) { wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); goto fail; } wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); ret = 0; fail: crypto_ec_point_deinit(K, 1); return ret; } static int sae_derive_k_ffc(struct sae_data *sae, u8 *k) { struct crypto_bignum *K; int ret = -1; K = crypto_bignum_init(); if (K == NULL) goto fail; /* * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), * PEER-COMMIT-ELEMENT))) * If K is identity element (one), reject. * k = F(K) (= x coordinate) */ if (crypto_bignum_exptmod(sae->tmp->pwe_ffc, sae->peer_commit_scalar, sae->tmp->prime, K) < 0 || crypto_bignum_mulmod(K, sae->tmp->peer_commit_element_ffc, sae->tmp->prime, K) < 0 || crypto_bignum_exptmod(K, sae->tmp->sae_rand, sae->tmp->prime, K) < 0 || crypto_bignum_is_one(K) || crypto_bignum_to_bin(K, k, SAE_MAX_PRIME_LEN, sae->tmp->prime_len) < 0) { wpa_printf(MSG_DEBUG, "SAE: Failed to calculate K and k"); goto fail; } wpa_hexdump_key(MSG_DEBUG, "SAE: k", k, sae->tmp->prime_len); ret = 0; fail: crypto_bignum_deinit(K, 1); return ret; } static int sae_kdf_hash(size_t hash_len, const u8 *k, const char *label, const u8 *context, size_t context_len, u8 *out, size_t out_len) { if (hash_len == 32) return sha256_prf(k, hash_len, label, context, context_len, out, out_len); #ifdef CONFIG_SHA384 if (hash_len == 48) return sha384_prf(k, hash_len, label, context, context_len, out, out_len); #endif /* CONFIG_SHA384 */ #ifdef CONFIG_SHA512 if (hash_len == 64) return sha512_prf(k, hash_len, label, context, context_len, out, out_len); #endif /* CONFIG_SHA512 */ return -1; } static int sae_derive_keys(struct sae_data *sae, const u8 *k) { u8 zero[SAE_MAX_HASH_LEN], val[SAE_MAX_PRIME_LEN]; const u8 *salt; struct wpabuf *rejected_groups = NULL; u8 keyseed[SAE_MAX_HASH_LEN]; u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN]; struct crypto_bignum *tmp; int ret = -1; size_t hash_len, salt_len, prime_len = sae->tmp->prime_len; const u8 *addr[1]; size_t len[1]; tmp = crypto_bignum_init(); if (tmp == NULL) goto fail; /* keyseed = H(salt, k) * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK", * (commit-scalar + peer-commit-scalar) modulo r) * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) * * When SAE-PK is used, * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context) */ if (!sae->h2e) hash_len = SHA256_MAC_LEN; else if (sae->tmp->dh) hash_len = sae_ffc_prime_len_2_hash_len(prime_len); else hash_len = sae_ecc_prime_len_2_hash_len(prime_len); if (sae->h2e && (sae->tmp->own_rejected_groups || sae->tmp->peer_rejected_groups)) { struct wpabuf *own, *peer; own = sae->tmp->own_rejected_groups; peer = sae->tmp->peer_rejected_groups; salt_len = 0; if (own) salt_len += wpabuf_len(own); if (peer) salt_len += wpabuf_len(peer); rejected_groups = wpabuf_alloc(salt_len); if (!rejected_groups) goto fail; if (sae->tmp->own_addr_higher) { if (own) wpabuf_put_buf(rejected_groups, own); if (peer) wpabuf_put_buf(rejected_groups, peer); } else { if (peer) wpabuf_put_buf(rejected_groups, peer); if (own) wpabuf_put_buf(rejected_groups, own); } salt = wpabuf_head(rejected_groups); salt_len = wpabuf_len(rejected_groups); } else { os_memset(zero, 0, hash_len); salt = zero; salt_len = hash_len; } wpa_hexdump(MSG_DEBUG, "SAE: salt for keyseed derivation", salt, salt_len); addr[0] = k; len[0] = prime_len; if (hkdf_extract(hash_len, salt, salt_len, 1, addr, len, keyseed) < 0) goto fail; wpa_hexdump_key(MSG_DEBUG, "SAE: keyseed", keyseed, hash_len); if (crypto_bignum_add(sae->tmp->own_commit_scalar, sae->peer_commit_scalar, tmp) < 0 || crypto_bignum_mod(tmp, sae->tmp->order, tmp) < 0) goto fail; /* IEEE Std 802.11-2016 is not exactly clear on the encoding of the bit * string that is needed for KCK, PMK, and PMKID derivation, but it * seems to make most sense to encode the * (commit-scalar + peer-commit-scalar) mod r part as a bit string by * zero padding it from left to the length of the order (in full * octets). */ crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len); wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); #ifdef CONFIG_SAE_PK if (sae->pk) { if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", val, sae->tmp->order_len, keys, 2 * hash_len + SAE_PMK_LEN) < 0) goto fail; } else { if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", val, sae->tmp->order_len, keys, hash_len + SAE_PMK_LEN) < 0) goto fail; } #else /* CONFIG_SAE_PK */ if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", val, sae->tmp->order_len, keys, hash_len + SAE_PMK_LEN) < 0) goto fail; #endif /* !CONFIG_SAE_PK */ forced_memzero(keyseed, sizeof(keyseed)); os_memcpy(sae->tmp->kck, keys, hash_len); sae->tmp->kck_len = hash_len; os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN); os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); #ifdef CONFIG_SAE_PK if (sae->pk) { os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN, hash_len); sae->tmp->kek_len = hash_len; wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK", sae->tmp->kek, sae->tmp->kek_len); } #endif /* CONFIG_SAE_PK */ forced_memzero(keys, sizeof(keys)); wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, sae->tmp->kck_len); wpa_hexdump_key(MSG_DEBUG, "SAE: PMK", sae->pmk, SAE_PMK_LEN); ret = 0; fail: wpabuf_free(rejected_groups); crypto_bignum_deinit(tmp, 0); return ret; } int sae_process_commit(struct sae_data *sae) { u8 k[SAE_MAX_PRIME_LEN]; if (sae->tmp == NULL || (sae->tmp->ec && sae_derive_k_ecc(sae, k) < 0) || (sae->tmp->dh && sae_derive_k_ffc(sae, k) < 0) || sae_derive_keys(sae, k) < 0) return -1; return 0; } int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, const struct wpabuf *token, const char *identifier) { u8 *pos; if (sae->tmp == NULL) return -1; wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ if (!sae->h2e && token) { wpabuf_put_buf(buf, token); wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", wpabuf_head(token), wpabuf_len(token)); } pos = wpabuf_put(buf, sae->tmp->prime_len); if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, sae->tmp->prime_len, sae->tmp->prime_len) < 0) return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", pos, sae->tmp->prime_len); if (sae->tmp->ec) { pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); if (crypto_ec_point_to_bin(sae->tmp->ec, sae->tmp->own_commit_element_ecc, pos, pos + sae->tmp->prime_len) < 0) return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", pos, sae->tmp->prime_len); wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", pos + sae->tmp->prime_len, sae->tmp->prime_len); } else { pos = wpabuf_put(buf, sae->tmp->prime_len); if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, sae->tmp->prime_len, sae->tmp->prime_len) < 0) return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", pos, sae->tmp->prime_len); } if (identifier) { /* Password Identifier element */ wpabuf_put_u8(buf, WLAN_EID_EXTENSION); wpabuf_put_u8(buf, 1 + os_strlen(identifier)); wpabuf_put_u8(buf, WLAN_EID_EXT_PASSWORD_IDENTIFIER); wpabuf_put_str(buf, identifier); wpa_printf(MSG_DEBUG, "SAE: own Password Identifier: %s", identifier); } if (sae->h2e && sae->tmp->own_rejected_groups) { wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups", sae->tmp->own_rejected_groups); wpabuf_put_u8(buf, WLAN_EID_EXTENSION); wpabuf_put_u8(buf, 1 + wpabuf_len(sae->tmp->own_rejected_groups)); wpabuf_put_u8(buf, WLAN_EID_EXT_REJECTED_GROUPS); wpabuf_put_buf(buf, sae->tmp->own_rejected_groups); } if (sae->h2e && token) { wpabuf_put_u8(buf, WLAN_EID_EXTENSION); wpabuf_put_u8(buf, 1 + wpabuf_len(token)); wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN); wpabuf_put_buf(buf, token); wpa_hexdump_buf(MSG_DEBUG, "SAE: Anti-clogging token (in container)", token); } return 0; } u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group) { if (allowed_groups) { int i; for (i = 0; allowed_groups[i] > 0; i++) { if (allowed_groups[i] == group) break; } if (allowed_groups[i] != group) { wpa_printf(MSG_DEBUG, "SAE: Proposed group %u not " "enabled in the current configuration", group); return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; } } if (sae->state == SAE_COMMITTED && group != sae->group) { wpa_printf(MSG_DEBUG, "SAE: Do not allow group to be changed"); return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; } if (group != sae->group && sae_set_group(sae, group) < 0) { wpa_printf(MSG_DEBUG, "SAE: Unsupported Finite Cyclic Group %u", group); return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; } if (sae->tmp == NULL) { wpa_printf(MSG_DEBUG, "SAE: Group information not yet initialized"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } if (sae->tmp->dh && !allowed_groups) { wpa_printf(MSG_DEBUG, "SAE: Do not allow FFC group %u without " "explicit configuration enabling it", group); return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; } return WLAN_STATUS_SUCCESS; } static int sae_is_password_id_elem(const u8 *pos, const u8 *end) { return end - pos >= 3 && pos[0] == WLAN_EID_EXTENSION && pos[1] >= 1 && end - pos - 2 >= pos[1] && pos[2] == WLAN_EID_EXT_PASSWORD_IDENTIFIER; } static int sae_is_rejected_groups_elem(const u8 *pos, const u8 *end) { return end - pos >= 3 && pos[0] == WLAN_EID_EXTENSION && pos[1] >= 2 && end - pos - 2 >= pos[1] && pos[2] == WLAN_EID_EXT_REJECTED_GROUPS; } static int sae_is_token_container_elem(const u8 *pos, const u8 *end) { return end - pos >= 3 && pos[0] == WLAN_EID_EXTENSION && pos[1] >= 1 && end - pos - 2 >= pos[1] && pos[2] == WLAN_EID_EXT_ANTI_CLOGGING_TOKEN; } static void sae_parse_commit_token(struct sae_data *sae, const u8 **pos, const u8 *end, const u8 **token, size_t *token_len, int h2e) { size_t scalar_elem_len, tlen; if (token) *token = NULL; if (token_len) *token_len = 0; if (h2e) return; /* No Anti-Clogging Token field outside container IE */ scalar_elem_len = (sae->tmp->ec ? 3 : 2) * sae->tmp->prime_len; if (scalar_elem_len >= (size_t) (end - *pos)) return; /* No extra data beyond peer scalar and element */ tlen = end - (*pos + scalar_elem_len); if (tlen < SHA256_MAC_LEN) { wpa_printf(MSG_DEBUG, "SAE: Too short optional data (%u octets) to include our Anti-Clogging Token", (unsigned int) tlen); return; } wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token", *pos, tlen); if (token) *token = *pos; if (token_len) *token_len = tlen; *pos += tlen; } static void sae_parse_token_container(struct sae_data *sae, const u8 *pos, const u8 *end, const u8 **token, size_t *token_len) { wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", pos, end - pos); if (!sae_is_token_container_elem(pos, end)) return; *token = pos + 3; *token_len = pos[1] - 1; wpa_hexdump(MSG_DEBUG, "SAE: Anti-Clogging Token (in container)", *token, *token_len); } static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos, const u8 *end) { struct crypto_bignum *peer_scalar; if (sae->tmp->prime_len > end - *pos) { wpa_printf(MSG_DEBUG, "SAE: Not enough data for scalar"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } peer_scalar = crypto_bignum_init_set(*pos, sae->tmp->prime_len); if (peer_scalar == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; /* * IEEE Std 802.11-2012, 11.3.8.6.1: If there is a protocol instance for * the peer and it is in Authenticated state, the new Commit Message * shall be dropped if the peer-scalar is identical to the one used in * the existing protocol instance. */ if (sae->state == SAE_ACCEPTED && sae->peer_commit_scalar_accepted && crypto_bignum_cmp(sae->peer_commit_scalar_accepted, peer_scalar) == 0) { wpa_printf(MSG_DEBUG, "SAE: Do not accept re-use of previous " "peer-commit-scalar"); crypto_bignum_deinit(peer_scalar, 0); return WLAN_STATUS_UNSPECIFIED_FAILURE; } /* 1 < scalar < r */ if (crypto_bignum_is_zero(peer_scalar) || crypto_bignum_is_one(peer_scalar) || crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) { wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar"); crypto_bignum_deinit(peer_scalar, 0); return WLAN_STATUS_UNSPECIFIED_FAILURE; } crypto_bignum_deinit(sae->peer_commit_scalar, 0); sae->peer_commit_scalar = peer_scalar; wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-scalar", *pos, sae->tmp->prime_len); *pos += sae->tmp->prime_len; return WLAN_STATUS_SUCCESS; } static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 **pos, const u8 *end) { u8 prime[SAE_MAX_ECC_PRIME_LEN]; if (2 * sae->tmp->prime_len > end - *pos) { wpa_printf(MSG_DEBUG, "SAE: Not enough data for " "commit-element"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime), sae->tmp->prime_len) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; /* element x and y coordinates < p */ if (os_memcmp(*pos, prime, sae->tmp->prime_len) >= 0 || os_memcmp(*pos + sae->tmp->prime_len, prime, sae->tmp->prime_len) >= 0) { wpa_printf(MSG_DEBUG, "SAE: Invalid coordinates in peer " "element"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(x)", *pos, sae->tmp->prime_len); wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element(y)", *pos + sae->tmp->prime_len, sae->tmp->prime_len); crypto_ec_point_deinit(sae->tmp->peer_commit_element_ecc, 0); sae->tmp->peer_commit_element_ecc = crypto_ec_point_from_bin(sae->tmp->ec, *pos); if (sae->tmp->peer_commit_element_ecc == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; if (!crypto_ec_point_is_on_curve(sae->tmp->ec, sae->tmp->peer_commit_element_ecc)) { wpa_printf(MSG_DEBUG, "SAE: Peer element is not on curve"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } *pos += 2 * sae->tmp->prime_len; return WLAN_STATUS_SUCCESS; } static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 **pos, const u8 *end) { struct crypto_bignum *res, *one; const u8 one_bin[1] = { 0x01 }; if (sae->tmp->prime_len > end - *pos) { wpa_printf(MSG_DEBUG, "SAE: Not enough data for " "commit-element"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } wpa_hexdump(MSG_DEBUG, "SAE: Peer commit-element", *pos, sae->tmp->prime_len); crypto_bignum_deinit(sae->tmp->peer_commit_element_ffc, 0); sae->tmp->peer_commit_element_ffc = crypto_bignum_init_set(*pos, sae->tmp->prime_len); if (sae->tmp->peer_commit_element_ffc == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; /* 1 < element < p - 1 */ res = crypto_bignum_init(); one = crypto_bignum_init_set(one_bin, sizeof(one_bin)); if (!res || !one || crypto_bignum_sub(sae->tmp->prime, one, res) || crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) || crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) || crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) { crypto_bignum_deinit(res, 0); crypto_bignum_deinit(one, 0); wpa_printf(MSG_DEBUG, "SAE: Invalid peer element"); return WLAN_STATUS_UNSPECIFIED_FAILURE; } crypto_bignum_deinit(one, 0); /* scalar-op(r, ELEMENT) = 1 modulo p */ if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc, sae->tmp->order, sae->tmp->prime, res) < 0 || !crypto_bignum_is_one(res)) { wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)"); crypto_bignum_deinit(res, 0); return WLAN_STATUS_UNSPECIFIED_FAILURE; } crypto_bignum_deinit(res, 0); *pos += sae->tmp->prime_len; return WLAN_STATUS_SUCCESS; } static u16 sae_parse_commit_element(struct sae_data *sae, const u8 **pos, const u8 *end) { if (sae->tmp->dh) return sae_parse_commit_element_ffc(sae, pos, end); return sae_parse_commit_element_ecc(sae, pos, end); } static int sae_parse_password_identifier(struct sae_data *sae, const u8 **pos, const u8 *end) { const u8 *epos; u8 len; wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", *pos, end - *pos); if (!sae_is_password_id_elem(*pos, end)) { if (sae->tmp->pw_id) { wpa_printf(MSG_DEBUG, "SAE: No Password Identifier included, but expected one (%s)", sae->tmp->pw_id); return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; } os_free(sae->tmp->pw_id); sae->tmp->pw_id = NULL; return WLAN_STATUS_SUCCESS; /* No Password Identifier */ } epos = *pos; epos++; /* skip IE type */ len = *epos++; /* IE length */ if (len > end - epos || len < 1) return WLAN_STATUS_UNSPECIFIED_FAILURE; epos++; /* skip ext ID */ len--; if (sae->tmp->pw_id && (len != os_strlen(sae->tmp->pw_id) || os_memcmp(sae->tmp->pw_id, epos, len) != 0)) { wpa_printf(MSG_DEBUG, "SAE: The included Password Identifier does not match the expected one (%s)", sae->tmp->pw_id); return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; } os_free(sae->tmp->pw_id); sae->tmp->pw_id = os_malloc(len + 1); if (!sae->tmp->pw_id) return WLAN_STATUS_UNSPECIFIED_FAILURE; os_memcpy(sae->tmp->pw_id, epos, len); sae->tmp->pw_id[len] = '\0'; wpa_hexdump_ascii(MSG_DEBUG, "SAE: Received Password Identifier", sae->tmp->pw_id, len); *pos = epos + len; return WLAN_STATUS_SUCCESS; } static int sae_parse_rejected_groups(struct sae_data *sae, const u8 **pos, const u8 *end) { const u8 *epos; u8 len; wpa_hexdump(MSG_DEBUG, "SAE: Possible elements at the end of the frame", *pos, end - *pos); if (!sae_is_rejected_groups_elem(*pos, end)) return WLAN_STATUS_SUCCESS; epos = *pos; epos++; /* skip IE type */ len = *epos++; /* IE length */ if (len > end - epos || len < 1) return WLAN_STATUS_UNSPECIFIED_FAILURE; epos++; /* skip ext ID */ len--; wpabuf_free(sae->tmp->peer_rejected_groups); sae->tmp->peer_rejected_groups = wpabuf_alloc(len); if (!sae->tmp->peer_rejected_groups) return WLAN_STATUS_UNSPECIFIED_FAILURE; wpabuf_put_data(sae->tmp->peer_rejected_groups, epos, len); wpa_hexdump_buf(MSG_DEBUG, "SAE: Received Rejected Groups list", sae->tmp->peer_rejected_groups); *pos = epos + len; return WLAN_STATUS_SUCCESS; } u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, const u8 **token, size_t *token_len, int *allowed_groups, int h2e) { const u8 *pos = data, *end = data + len; u16 res; /* Check Finite Cyclic Group */ if (end - pos < 2) return WLAN_STATUS_UNSPECIFIED_FAILURE; res = sae_group_allowed(sae, allowed_groups, WPA_GET_LE16(pos)); if (res != WLAN_STATUS_SUCCESS) return res; pos += 2; /* Optional Anti-Clogging Token */ sae_parse_commit_token(sae, &pos, end, token, token_len, h2e); /* commit-scalar */ res = sae_parse_commit_scalar(sae, &pos, end); if (res != WLAN_STATUS_SUCCESS) return res; /* commit-element */ res = sae_parse_commit_element(sae, &pos, end); if (res != WLAN_STATUS_SUCCESS) return res; /* Optional Password Identifier element */ res = sae_parse_password_identifier(sae, &pos, end); if (res != WLAN_STATUS_SUCCESS) return res; /* Conditional Rejected Groups element */ if (h2e) { res = sae_parse_rejected_groups(sae, &pos, end); if (res != WLAN_STATUS_SUCCESS) return res; } /* Optional Anti-Clogging Token Container element */ if (h2e) sae_parse_token_container(sae, pos, end, token, token_len); /* * Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as * the values we sent which would be evidence of a reflection attack. */ if (!sae->tmp->own_commit_scalar || crypto_bignum_cmp(sae->tmp->own_commit_scalar, sae->peer_commit_scalar) != 0 || (sae->tmp->dh && (!sae->tmp->own_commit_element_ffc || crypto_bignum_cmp(sae->tmp->own_commit_element_ffc, sae->tmp->peer_commit_element_ffc) != 0)) || (sae->tmp->ec && (!sae->tmp->own_commit_element_ecc || crypto_ec_point_cmp(sae->tmp->ec, sae->tmp->own_commit_element_ecc, sae->tmp->peer_commit_element_ecc) != 0))) return WLAN_STATUS_SUCCESS; /* scalars/elements are different */ /* * This is a reflection attack - return special value to trigger caller * to silently discard the frame instead of replying with a specific * status code. */ return SAE_SILENTLY_DISCARD; } static int sae_cn_confirm(struct sae_data *sae, const u8 *sc, const struct crypto_bignum *scalar1, const u8 *element1, size_t element1_len, const struct crypto_bignum *scalar2, const u8 *element2, size_t element2_len, u8 *confirm) { const u8 *addr[5]; size_t len[5]; u8 scalar_b1[SAE_MAX_PRIME_LEN], scalar_b2[SAE_MAX_PRIME_LEN]; /* Confirm * CN(key, X, Y, Z, ...) = * HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) | ...) * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, * peer-commit-scalar, PEER-COMMIT-ELEMENT) * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) */ if (crypto_bignum_to_bin(scalar1, scalar_b1, sizeof(scalar_b1), sae->tmp->prime_len) < 0 || crypto_bignum_to_bin(scalar2, scalar_b2, sizeof(scalar_b2), sae->tmp->prime_len) < 0) return -1; addr[0] = sc; len[0] = 2; addr[1] = scalar_b1; len[1] = sae->tmp->prime_len; addr[2] = element1; len[2] = element1_len; addr[3] = scalar_b2; len[3] = sae->tmp->prime_len; addr[4] = element2; len[4] = element2_len; return hkdf_extract(sae->tmp->kck_len, sae->tmp->kck, sae->tmp->kck_len, 5, addr, len, confirm); } static int sae_cn_confirm_ecc(struct sae_data *sae, const u8 *sc, const struct crypto_bignum *scalar1, const struct crypto_ec_point *element1, const struct crypto_bignum *scalar2, const struct crypto_ec_point *element2, u8 *confirm) { u8 element_b1[2 * SAE_MAX_ECC_PRIME_LEN]; u8 element_b2[2 * SAE_MAX_ECC_PRIME_LEN]; if (crypto_ec_point_to_bin(sae->tmp->ec, element1, element_b1, element_b1 + sae->tmp->prime_len) < 0 || crypto_ec_point_to_bin(sae->tmp->ec, element2, element_b2, element_b2 + sae->tmp->prime_len) < 0 || sae_cn_confirm(sae, sc, scalar1, element_b1, 2 * sae->tmp->prime_len, scalar2, element_b2, 2 * sae->tmp->prime_len, confirm) < 0) return -1; return 0; } static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, const struct crypto_bignum *scalar1, const struct crypto_bignum *element1, const struct crypto_bignum *scalar2, const struct crypto_bignum *element2, u8 *confirm) { u8 element_b1[SAE_MAX_PRIME_LEN]; u8 element_b2[SAE_MAX_PRIME_LEN]; if (crypto_bignum_to_bin(element1, element_b1, sizeof(element_b1), sae->tmp->prime_len) < 0 || crypto_bignum_to_bin(element2, element_b2, sizeof(element_b2), sae->tmp->prime_len) < 0 || sae_cn_confirm(sae, sc, scalar1, element_b1, sae->tmp->prime_len, scalar2, element_b2, sae->tmp->prime_len, confirm) < 0) return -1; return 0; } int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) { const u8 *sc; size_t hash_len; int res; if (sae->tmp == NULL) return -1; hash_len = sae->tmp->kck_len; /* Send-Confirm */ if (sae->send_confirm < 0xffff) sae->send_confirm++; sc = wpabuf_put(buf, 0); wpabuf_put_le16(buf, sae->send_confirm); if (sae->tmp->ec) res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, sae->tmp->own_commit_element_ecc, sae->peer_commit_scalar, sae->tmp->peer_commit_element_ecc, wpabuf_put(buf, hash_len)); else res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, sae->tmp->own_commit_element_ffc, sae->peer_commit_scalar, sae->tmp->peer_commit_element_ffc, wpabuf_put(buf, hash_len)); if (res) return res; #ifdef CONFIG_SAE_PK if (sae_write_confirm_pk(sae, buf) < 0) return -1; #endif /* CONFIG_SAE_PK */ return 0; } int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) { u8 verifier[SAE_MAX_HASH_LEN]; size_t hash_len; if (!sae->tmp) return -1; hash_len = sae->tmp->kck_len; if (len < 2 + hash_len) { wpa_printf(MSG_DEBUG, "SAE: Too short confirm message"); return -1; } wpa_printf(MSG_DEBUG, "SAE: peer-send-confirm %u", WPA_GET_LE16(data)); if (!sae->peer_commit_scalar || !sae->tmp->own_commit_scalar) { wpa_printf(MSG_DEBUG, "SAE: Temporary data not yet available"); return -1; } if (sae->tmp->ec) { if (!sae->tmp->peer_commit_element_ecc || !sae->tmp->own_commit_element_ecc || sae_cn_confirm_ecc(sae, data, sae->peer_commit_scalar, sae->tmp->peer_commit_element_ecc, sae->tmp->own_commit_scalar, sae->tmp->own_commit_element_ecc, verifier) < 0) return -1; } else { if (!sae->tmp->peer_commit_element_ffc || !sae->tmp->own_commit_element_ffc || sae_cn_confirm_ffc(sae, data, sae->peer_commit_scalar, sae->tmp->peer_commit_element_ffc, sae->tmp->own_commit_scalar, sae->tmp->own_commit_element_ffc, verifier) < 0) return -1; } if (os_memcmp_const(verifier, data + 2, hash_len) != 0) { wpa_printf(MSG_DEBUG, "SAE: Confirm mismatch"); wpa_hexdump(MSG_DEBUG, "SAE: Received confirm", data + 2, hash_len); wpa_hexdump(MSG_DEBUG, "SAE: Calculated verifier", verifier, hash_len); return -1; } #ifdef CONFIG_SAE_PK if (sae_check_confirm_pk(sae, data + 2 + hash_len, len - 2 - hash_len) < 0) return -1; #endif /* CONFIG_SAE_PK */ return 0; } const char * sae_state_txt(enum sae_state state) { switch (state) { case SAE_NOTHING: return "Nothing"; case SAE_COMMITTED: return "Committed"; case SAE_CONFIRMED: return "Confirmed"; case SAE_ACCEPTED: return "Accepted"; } return "?"; } diff --git a/contrib/wpa/src/common/version.h b/contrib/wpa/src/common/version.h index 0235c9bf6776..7502f58e0b87 100644 --- a/contrib/wpa/src/common/version.h +++ b/contrib/wpa/src/common/version.h @@ -1,14 +1,14 @@ #ifndef VERSION_H #define VERSION_H #ifndef VERSION_STR_POSTFIX #define VERSION_STR_POSTFIX "" #endif /* VERSION_STR_POSTFIX */ #ifndef GIT_VERSION_STR_POSTFIX #define GIT_VERSION_STR_POSTFIX "" #endif /* GIT_VERSION_STR_POSTFIX */ -#define VERSION_STR "2.10-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX +#define VERSION_STR "2.10" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX #endif /* VERSION_H */ diff --git a/contrib/wpa/src/crypto/crypto.h b/contrib/wpa/src/crypto/crypto.h index eb600699d3d0..e6150b0cf16e 100644 --- a/contrib/wpa/src/crypto/crypto.h +++ b/contrib/wpa/src/crypto/crypto.h @@ -1,1290 +1,1278 @@ /* * Wrapper functions for crypto libraries * Copyright (c) 2004-2017, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. * * This file defines the cryptographic functions that need to be implemented * for wpa_supplicant and hostapd. When TLS is not used, internal * implementation of MD5, SHA1, and AES is used and no external libraries are * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the * crypto library used by the TLS implementation is expected to be used for * non-TLS needs, too, in order to save space by not implementing these * functions twice. * * Wrapper code for using each crypto library is in its own file (crypto*.c) * and one of these files is build and linked in to provide the functions * defined here. */ #ifndef CRYPTO_H #define CRYPTO_H /** * md4_vector - MD4 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * md5_vector - MD5 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * sha1_vector - SHA-1 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF * @seed: Seed/key for the PRF * @seed_len: Seed length in bytes * @x: Buffer for PRF output * @xlen: Output length in bytes * Returns: 0 on success, -1 on failure * * This function implements random number generation specified in NIST FIPS * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to * SHA-1, but has different message padding. */ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen); /** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * sha384_vector - SHA384 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * sha512_vector - SHA512 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * des_encrypt - Encrypt one block with DES * @clear: 8 octets (in) * @key: 7 octets (in) (no parity bits included) * @cypher: 8 octets (out) * Returns: 0 on success, -1 on failure */ int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); /** * aes_encrypt_init - Initialize AES for encryption * @key: Encryption key * @len: Key length in bytes (usually 16, i.e., 128 bits) * Returns: Pointer to context data or %NULL on failure */ void * aes_encrypt_init(const u8 *key, size_t len); /** * aes_encrypt - Encrypt one AES block * @ctx: Context pointer from aes_encrypt_init() * @plain: Plaintext data to be encrypted (16 bytes) * @crypt: Buffer for the encrypted data (16 bytes) * Returns: 0 on success, -1 on failure */ int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); /** * aes_encrypt_deinit - Deinitialize AES encryption * @ctx: Context pointer from aes_encrypt_init() */ void aes_encrypt_deinit(void *ctx); /** * aes_decrypt_init - Initialize AES for decryption * @key: Decryption key * @len: Key length in bytes (usually 16, i.e., 128 bits) * Returns: Pointer to context data or %NULL on failure */ void * aes_decrypt_init(const u8 *key, size_t len); /** * aes_decrypt - Decrypt one AES block * @ctx: Context pointer from aes_encrypt_init() * @crypt: Encrypted data (16 bytes) * @plain: Buffer for the decrypted data (16 bytes) * Returns: 0 on success, -1 on failure */ int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); /** * aes_decrypt_deinit - Deinitialize AES decryption * @ctx: Context pointer from aes_encrypt_init() */ void aes_decrypt_deinit(void *ctx); enum crypto_hash_alg { CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1, CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256, CRYPTO_HASH_ALG_SHA384, CRYPTO_HASH_ALG_SHA512 }; struct crypto_hash; /** * crypto_hash_init - Initialize hash/HMAC function * @alg: Hash algorithm * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed * @key_len: Length of the key in bytes * Returns: Pointer to hash context to use with other hash functions or %NULL * on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len); /** * crypto_hash_update - Add data to hash calculation * @ctx: Context pointer from crypto_hash_init() * @data: Data buffer to add * @len: Length of the buffer * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); /** * crypto_hash_finish - Complete hash calculation * @ctx: Context pointer from crypto_hash_init() * @hash: Buffer for hash value or %NULL if caller is just freeing the hash * context * @len: Pointer to length of the buffer or %NULL if caller is just freeing the * hash context; on return, this is set to the actual length of the hash value * Returns: 0 on success, -1 if buffer is too small (len set to needed length), * or -2 on other failures (including failed crypto_hash_update() operations) * * This function calculates the hash value and frees the context buffer that * was used for hash calculation. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); enum crypto_cipher_alg { CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4 }; struct crypto_cipher; /** * crypto_cipher_init - Initialize block/stream cipher function * @alg: Cipher algorithm * @iv: Initialization vector for block ciphers or %NULL for stream ciphers * @key: Cipher key * @key_len: Length of key in bytes * Returns: Pointer to cipher context to use with other cipher functions or * %NULL on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len); /** * crypto_cipher_encrypt - Cipher encrypt * @ctx: Context pointer from crypto_cipher_init() * @plain: Plaintext to cipher * @crypt: Resulting ciphertext * @len: Length of the plaintext * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len); /** * crypto_cipher_decrypt - Cipher decrypt * @ctx: Context pointer from crypto_cipher_init() * @crypt: Ciphertext to decrypt * @plain: Resulting plaintext * @len: Length of the cipher text * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len); /** * crypto_cipher_decrypt - Free cipher context * @ctx: Context pointer from crypto_cipher_init() * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_cipher_deinit(struct crypto_cipher *ctx); struct crypto_public_key; struct crypto_private_key; /** * crypto_public_key_import - Import an RSA public key * @key: Key buffer (DER encoded RSA public key) * @len: Key buffer length in bytes * Returns: Pointer to the public key or %NULL on failure * * This function can just return %NULL if the crypto library supports X.509 * parsing. In that case, crypto_public_key_from_cert() is used to import the * public key from a certificate. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); struct crypto_public_key * crypto_public_key_import_parts(const u8 *n, size_t n_len, const u8 *e, size_t e_len); /** * crypto_private_key_import - Import an RSA private key * @key: Key buffer (DER encoded RSA private key) * @len: Key buffer length in bytes * @passwd: Key encryption password or %NULL if key is not encrypted * Returns: Pointer to the private key or %NULL on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd); /** * crypto_public_key_from_cert - Import an RSA public key from a certificate * @buf: DER encoded X.509 certificate * @len: Certificate buffer length in bytes * Returns: Pointer to public key or %NULL on failure * * This function can just return %NULL if the crypto library does not support * X.509 parsing. In that case, internal code will be used to parse the * certificate and public key is imported using crypto_public_key_import(). * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len); /** * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5) * @key: Public key * @in: Plaintext buffer * @inlen: Length of plaintext buffer in bytes * @out: Output buffer for encrypted data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_public_key_encrypt_pkcs1_v15( struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5) * @key: Private key * @in: Encrypted buffer * @inlen: Length of encrypted buffer in bytes * @out: Output buffer for encrypted data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_private_key_decrypt_pkcs1_v15( struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1) * @key: Private key from crypto_private_key_import() * @in: Plaintext buffer * @inlen: Length of plaintext buffer in bytes * @out: Output buffer for encrypted (signed) data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_public_key_free - Free public key * @key: Public key * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_public_key_free(struct crypto_public_key *key); /** * crypto_private_key_free - Free private key * @key: Private key from crypto_private_key_import() * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_private_key_free(struct crypto_private_key *key); /** * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature * @key: Public key * @crypt: Encrypted signature data (using the private key) * @crypt_len: Encrypted signature data length * @plain: Buffer for plaintext (at least crypt_len bytes) * @plain_len: Plaintext length (max buffer size on input, real len on output); * Returns: 0 on success, -1 on failure */ int __must_check crypto_public_key_decrypt_pkcs1( struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len); int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, u8 *pubkey); int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, const u8 *order, size_t order_len, const u8 *privkey, size_t privkey_len, const u8 *pubkey, size_t pubkey_len, u8 *secret, size_t *len); /** * crypto_global_init - Initialize crypto wrapper * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_global_init(void); /** * crypto_global_deinit - Deinitialize crypto wrapper * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_global_deinit(void); /** * crypto_mod_exp - Modular exponentiation of large integers * @base: Base integer (big endian byte array) * @base_len: Length of base integer in bytes * @power: Power integer (big endian byte array) * @power_len: Length of power integer in bytes * @modulus: Modulus integer (big endian byte array) * @modulus_len: Length of modulus integer in bytes * @result: Buffer for the result * @result_len: Result length (max buffer size on input, real len on output) * Returns: 0 on success, -1 on failure * * This function calculates result = base ^ power mod modulus. modules_len is * used as the maximum size of modulus buffer. It is set to the used size on * success. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len); /** * rc4_skip - XOR RC4 stream to given data with skip-stream-start * @key: RC4 key * @keylen: RC4 key length * @skip: number of bytes to skip from the beginning of the RC4 stream * @data: data to be XOR'ed with RC4 stream * @data_len: buf length * Returns: 0 on success, -1 on failure * * Generate RC4 pseudo random stream for the given key, skip beginning of the * stream, and XOR the end result with the data buffer to perform RC4 * encryption/decryption. */ int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len); /** * crypto_get_random - Generate cryptographically strong pseudo-random bytes * @buf: Buffer for data * @len: Number of bytes to generate * Returns: 0 on success, -1 on failure * * If the PRNG does not have enough entropy to ensure unpredictable byte * sequence, this functions must return -1. */ int crypto_get_random(void *buf, size_t len); /** * crypto_pkcs7_get_certificates - Extract X.509 certificates from PKCS#7 data * @pkcs7: DER encoded PKCS#7 data * Returns: Buffer of the extracted PEM X.509 certificates or %NULL on failure */ struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7); /** * struct crypto_bignum - bignum * * Internal data structure for bignum implementation. The contents is specific * to the used crypto library. */ struct crypto_bignum; /** * crypto_bignum_init - Allocate memory for bignum * Returns: Pointer to allocated bignum or %NULL on failure */ struct crypto_bignum * crypto_bignum_init(void); /** * crypto_bignum_init_set - Allocate memory for bignum and set the value * @buf: Buffer with unsigned binary value * @len: Length of buf in octets * Returns: Pointer to allocated bignum or %NULL on failure */ struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len); /** * crypto_bignum_init_set - Allocate memory for bignum and set the value (uint) * @val: Value to set * Returns: Pointer to allocated bignum or %NULL on failure */ struct crypto_bignum * crypto_bignum_init_uint(unsigned int val); /** * crypto_bignum_deinit - Free bignum * @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set() * @clear: Whether to clear the value from memory */ void crypto_bignum_deinit(struct crypto_bignum *n, int clear); /** * crypto_bignum_to_bin - Set binary buffer to unsigned bignum * @a: Bignum * @buf: Buffer for the binary number * @len: Length of @buf in octets * @padlen: Length in octets to pad the result to or 0 to indicate no padding * Returns: Number of octets written on success, -1 on failure */ int crypto_bignum_to_bin(const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen); /** * crypto_bignum_rand - Create a random number in range of modulus * @r: Bignum; set to a random value * @m: Bignum; modulus * Returns: 0 on success, -1 on failure */ int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m); /** * crypto_bignum_add - c = a + b * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result of a + b * Returns: 0 on success, -1 on failure */ int crypto_bignum_add(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c); /** * crypto_bignum_mod - c = a % b * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result of a % b * Returns: 0 on success, -1 on failure */ int crypto_bignum_mod(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c); /** * crypto_bignum_exptmod - Modular exponentiation: d = a^b (mod c) * @a: Bignum; base * @b: Bignum; exponent * @c: Bignum; modulus * @d: Bignum; used to store the result of a^b (mod c) * Returns: 0 on success, -1 on failure */ int crypto_bignum_exptmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d); /** * crypto_bignum_inverse - Inverse a bignum so that a * c = 1 (mod b) * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result * Returns: 0 on success, -1 on failure */ int crypto_bignum_inverse(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c); /** * crypto_bignum_sub - c = a - b * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result of a - b * Returns: 0 on success, -1 on failure */ int crypto_bignum_sub(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c); /** * crypto_bignum_div - c = a / b * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result of a / b * Returns: 0 on success, -1 on failure */ int crypto_bignum_div(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c); /** * crypto_bignum_addmod - d = a + b (mod c) * @a: Bignum * @b: Bignum * @c: Bignum * @d: Bignum; used to store the result of (a + b) % c * Returns: 0 on success, -1 on failure */ int crypto_bignum_addmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d); /** * crypto_bignum_mulmod - d = a * b (mod c) * @a: Bignum * @b: Bignum * @c: Bignum * @d: Bignum; used to store the result of (a * b) % c * Returns: 0 on success, -1 on failure */ int crypto_bignum_mulmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d); /** * crypto_bignum_sqrmod - c = a^2 (mod b) * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result of a^2 % b * Returns: 0 on success, -1 on failure */ int crypto_bignum_sqrmod(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c); /** * crypto_bignum_rshift - r = a >> n * @a: Bignum * @n: Number of bits * @r: Bignum; used to store the result of a >> n * Returns: 0 on success, -1 on failure */ int crypto_bignum_rshift(const struct crypto_bignum *a, int n, struct crypto_bignum *r); /** * crypto_bignum_cmp - Compare two bignums * @a: Bignum * @b: Bignum * Returns: -1 if a < b, 0 if a == b, or 1 if a > b */ int crypto_bignum_cmp(const struct crypto_bignum *a, const struct crypto_bignum *b); /** * crypto_bignum_is_zero - Is the given bignum zero * @a: Bignum * Returns: 1 if @a is zero or 0 if not */ int crypto_bignum_is_zero(const struct crypto_bignum *a); /** * crypto_bignum_is_one - Is the given bignum one * @a: Bignum * Returns: 1 if @a is one or 0 if not */ int crypto_bignum_is_one(const struct crypto_bignum *a); /** * crypto_bignum_is_odd - Is the given bignum odd * @a: Bignum * Returns: 1 if @a is odd or 0 if not */ int crypto_bignum_is_odd(const struct crypto_bignum *a); /** * crypto_bignum_legendre - Compute the Legendre symbol (a/p) * @a: Bignum * @p: Bignum * Returns: Legendre symbol -1,0,1 on success; -2 on calculation failure */ int crypto_bignum_legendre(const struct crypto_bignum *a, const struct crypto_bignum *p); /** * struct crypto_ec - Elliptic curve context * * Internal data structure for EC implementation. The contents is specific * to the used crypto library. */ struct crypto_ec; /** * struct crypto_ec_point - Elliptic curve point * * Internal data structure for EC implementation to represent a point. The * contents is specific to the used crypto library. */ struct crypto_ec_point; /** * crypto_ec_init - Initialize elliptic curve context * @group: Identifying number for the ECC group (IANA "Group Description" * attribute registrty for RFC 2409) * Returns: Pointer to EC context or %NULL on failure */ struct crypto_ec * crypto_ec_init(int group); /** * crypto_ec_deinit - Deinitialize elliptic curve context * @e: EC context from crypto_ec_init() */ void crypto_ec_deinit(struct crypto_ec *e); /** * crypto_ec_prime_len - Get length of the prime in octets * @e: EC context from crypto_ec_init() * Returns: Length of the prime defining the group */ size_t crypto_ec_prime_len(struct crypto_ec *e); /** * crypto_ec_prime_len_bits - Get length of the prime in bits * @e: EC context from crypto_ec_init() * Returns: Length of the prime defining the group in bits */ size_t crypto_ec_prime_len_bits(struct crypto_ec *e); /** * crypto_ec_order_len - Get length of the order in octets * @e: EC context from crypto_ec_init() * Returns: Length of the order defining the group */ size_t crypto_ec_order_len(struct crypto_ec *e); /** * crypto_ec_get_prime - Get prime defining an EC group * @e: EC context from crypto_ec_init() * Returns: Prime (bignum) defining the group */ const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e); /** * crypto_ec_get_order - Get order of an EC group * @e: EC context from crypto_ec_init() * Returns: Order (bignum) of the group */ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e); /** * crypto_ec_get_a - Get 'a' coefficient of an EC group's curve * @e: EC context from crypto_ec_init() * Returns: 'a' coefficient (bignum) of the group */ const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e); /** * crypto_ec_get_b - Get 'b' coeffiecient of an EC group's curve * @e: EC context from crypto_ec_init() * Returns: 'b' coefficient (bignum) of the group */ const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e); /** * crypto_ec_get_generator - Get generator point of the EC group's curve * @e: EC context from crypto_ec_init() * Returns: Pointer to generator point */ const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e); /** * crypto_ec_point_init - Initialize data for an EC point * @e: EC context from crypto_ec_init() * Returns: Pointer to EC point data or %NULL on failure */ struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e); /** * crypto_ec_point_deinit - Deinitialize EC point data * @p: EC point data from crypto_ec_point_init() * @clear: Whether to clear the EC point value from memory */ void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear); /** * crypto_ec_point_x - Copies the x-ordinate point into big number * @e: EC context from crypto_ec_init() * @p: EC point data * @x: Big number to set to the copy of x-ordinate * Returns: 0 on success, -1 on failure */ int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, struct crypto_bignum *x); /** * crypto_ec_point_to_bin - Write EC point value as binary data * @e: EC context from crypto_ec_init() * @p: EC point data from crypto_ec_point_init() * @x: Buffer for writing the binary data for x coordinate or %NULL if not used * @y: Buffer for writing the binary data for y coordinate or %NULL if not used * Returns: 0 on success, -1 on failure * * This function can be used to write an EC point as binary data in a format * that has the x and y coordinates in big endian byte order fields padded to * the length of the prime defining the group. */ int crypto_ec_point_to_bin(struct crypto_ec *e, const struct crypto_ec_point *point, u8 *x, u8 *y); /** * crypto_ec_point_from_bin - Create EC point from binary data * @e: EC context from crypto_ec_init() * @val: Binary data to read the EC point from * Returns: Pointer to EC point data or %NULL on failure * * This function readers x and y coordinates of the EC point from the provided * buffer assuming the values are in big endian byte order with fields padded to * the length of the prime defining the group. */ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, const u8 *val); /** * crypto_ec_point_add - c = a + b * @e: EC context from crypto_ec_init() * @a: Bignum * @b: Bignum * @c: Bignum; used to store the result of a + b * Returns: 0 on success, -1 on failure */ int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b, struct crypto_ec_point *c); /** * crypto_ec_point_mul - res = b * p * @e: EC context from crypto_ec_init() * @p: EC point * @b: Bignum * @res: EC point; used to store the result of b * p * Returns: 0 on success, -1 on failure */ int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, const struct crypto_bignum *b, struct crypto_ec_point *res); /** * crypto_ec_point_invert - Compute inverse of an EC point * @e: EC context from crypto_ec_init() * @p: EC point to invert (and result of the operation) * Returns: 0 on success, -1 on failure */ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p); -/** - * crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate - * @e: EC context from crypto_ec_init() - * @p: EC point to use for the returning the result - * @x: x coordinate - * @y_bit: y-bit (0 or 1) for selecting the y value to use - * Returns: 0 on success, -1 on failure - */ -int crypto_ec_point_solve_y_coord(struct crypto_ec *e, - struct crypto_ec_point *p, - const struct crypto_bignum *x, int y_bit); - /** * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b * @e: EC context from crypto_ec_init() * @x: x coordinate * Returns: y^2 on success, %NULL failure */ struct crypto_bignum * crypto_ec_point_compute_y_sqr(struct crypto_ec *e, const struct crypto_bignum *x); /** * crypto_ec_point_is_at_infinity - Check whether EC point is neutral element * @e: EC context from crypto_ec_init() * @p: EC point * Returns: 1 if the specified EC point is the neutral element of the group or * 0 if not */ int crypto_ec_point_is_at_infinity(struct crypto_ec *e, const struct crypto_ec_point *p); /** * crypto_ec_point_is_on_curve - Check whether EC point is on curve * @e: EC context from crypto_ec_init() * @p: EC point * Returns: 1 if the specified EC point is on the curve or 0 if not */ int crypto_ec_point_is_on_curve(struct crypto_ec *e, const struct crypto_ec_point *p); /** * crypto_ec_point_cmp - Compare two EC points * @e: EC context from crypto_ec_init() * @a: EC point * @b: EC point * Returns: 0 on equal, non-zero otherwise */ int crypto_ec_point_cmp(const struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b); /** * crypto_ec_point_debug_print - Dump EC point to debug log * @e: EC context from crypto_ec_init() * @p: EC point * @title: Name of the EC point in the trace */ void crypto_ec_point_debug_print(const struct crypto_ec *e, const struct crypto_ec_point *p, const char *title); /** * struct crypto_ec_key - Elliptic curve key pair * * Internal data structure for EC key pair. The contents is specific to the used * crypto library. */ struct crypto_ec_key; /** * struct crypto_ecdh - Elliptic Curve Diffie–Hellman context * * Internal data structure for ECDH. The contents is specific to the used * crypto library. */ struct crypto_ecdh; /** * crypto_ecdh_init - Initialize elliptic curve Diffie–Hellman context * @group: Identifying number for the ECC group (IANA "Group Description" * attribute registry for RFC 2409) * This function generates an ephemeral key pair. * Returns: Pointer to ECDH context or %NULL on failure */ struct crypto_ecdh * crypto_ecdh_init(int group); /** * crypto_ecdh_init2 - Initialize elliptic curve Diffie–Hellman context with a * given EC key * @group: Identifying number for the ECC group (IANA "Group Description" * attribute registry for RFC 2409) * @own_key: Our own EC Key * Returns: Pointer to ECDH context or %NULL on failure */ struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key); /** * crypto_ecdh_get_pubkey - Retrieve public key from ECDH context * @ecdh: ECDH context from crypto_ecdh_init() or crypto_ecdh_init2() * @inc_y: Whether public key should include y coordinate (explicit form) * or not (compressed form) * Returns: Binary data f the public key or %NULL on failure */ struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y); /** * crypto_ecdh_set_peerkey - Compute ECDH secret * @ecdh: ECDH context from crypto_ecdh_init() or crypto_ecdh_init2() * @inc_y: Whether peer's public key includes y coordinate (explicit form) * or not (compressed form) * @key: Binary data of the peer's public key * @len: Length of the @key buffer * Returns: Binary data with the EDCH secret or %NULL on failure */ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, const u8 *key, size_t len); /** * crypto_ecdh_deinit - Free ECDH context * @ecdh: ECDH context from crypto_ecdh_init() or crypto_ecdh_init2() */ void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); /** * crypto_ecdh_prime_len - Get length of the prime in octets * @e: ECDH context from crypto_ecdh_init() * Returns: Length of the prime defining the group */ size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh); /** * crypto_ec_key_parse_priv - Initialize EC key pair from ECPrivateKey ASN.1 * @der: DER encoding of ASN.1 ECPrivateKey * @der_len: Length of @der buffer * Returns: EC key or %NULL on failure */ struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len); /** * crypto_ec_key_parse_pub - Initialize EC key pair from SubjectPublicKeyInfo ASN.1 * @der: DER encoding of ASN.1 SubjectPublicKeyInfo * @der_len: Length of @der buffer * Returns: EC key or %NULL on failure */ struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len); /** * crypto_ec_key_set_pub - Initialize an EC public key from EC point coordinates * @group: Identifying number for the ECC group * @x: X coordinate of the public key * @y: Y coordinate of the public key * @len: Length of @x and @y buffer * Returns: EC key or %NULL on failure * * This function initialize an EC key from public key coordinates, in big endian * byte order padded to the length of the prime defining the group. */ struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x, const u8 *y, size_t len); /** * crypto_ec_key_set_pub_point - Initialize an EC public key from EC point * @e: EC context from crypto_ec_init() * @pub: Public key point * Returns: EC key or %NULL on failure */ struct crypto_ec_key * crypto_ec_key_set_pub_point(struct crypto_ec *e, const struct crypto_ec_point *pub); /** * crypto_ec_key_gen - Generate EC key pair * @group: Identifying number for the ECC group * Returns: EC key or %NULL on failure */ struct crypto_ec_key * crypto_ec_key_gen(int group); /** * crypto_ec_key_deinit - Free EC key * @key: EC key from crypto_ec_key_parse_pub/priv() or crypto_ec_key_gen() */ void crypto_ec_key_deinit(struct crypto_ec_key *key); /** * crypto_ec_key_get_subject_public_key - Get SubjectPublicKeyInfo ASN.1 for an EC key * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen() * Returns: Buffer with DER encoding of ASN.1 SubjectPublicKeyInfo or %NULL on failure */ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key); /** * crypto_ec_key_get_ecprivate_key - Get ECPrivateKey ASN.1 for a EC key * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen() * @include_pub: Whether to include public key in the ASN.1 sequence * Returns: Buffer with DER encoding of ASN.1 ECPrivateKey or %NULL on failure */ struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, bool include_pub); /** * crypto_ec_key_get_pubkey_point - Get public key point coordinates * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv() * @prefix: Whether output buffer should include the octet to indicate * coordinate form (as defined for SubjectPublicKeyInfo) * Returns: Buffer with coordinates of public key in uncompressed form or %NULL * on failure */ struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key, int prefix); /** * crypto_ec_key_get_public_key - Get EC public key as an EC point * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv() * Returns: Public key as an EC point or %NULL on failure */ const struct crypto_ec_point * crypto_ec_key_get_public_key(struct crypto_ec_key *key); /** * crypto_ec_key_get_private_key - Get EC private key as a bignum * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_parse_priv() * Returns: Private key as a bignum or %NULL on failure */ const struct crypto_bignum * crypto_ec_key_get_private_key(struct crypto_ec_key *key); /** * crypto_ec_key_sign - Sign a buffer with an EC key * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen() * @data: Data to sign * @len: Length of @data buffer * Returns: Buffer with DER encoding of ASN.1 Ecdsa-Sig-Value or %NULL on failure */ struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, size_t len); /** * crypto_ec_key_sign_r_s - Sign a buffer with an EC key * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen() * @data: Data to sign * @len: Length of @data buffer * Returns: Buffer with the concatenated r and s values. Each value is in big * endian byte order padded to the length of the prime defining the group of * the key. */ struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, const u8 *data, size_t len); /** * crypto_ec_key_verify_signature - Verify ECDSA signature * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen() * @data: Data to be signed * @len: Length of @data buffer * @sig: DER encoding of ASN.1 Ecdsa-Sig-Value * @sig_len: Length of @sig buffer * Returns: 1 if signature is valid, 0 if signature is invalid and -1 on failure */ int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *sig, size_t sig_len); /** * crypto_ec_key_verify_signature_r_s - Verify signature * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen() * @data: Data to signed * @len: Length of @data buffer * @r: Binary data, in big endian byte order, of the 'r' field of the ECDSA * signature. * @s: Binary data, in big endian byte order, of the 's' field of the ECDSA * signature. * @r_len: Length of @r buffer * @s_len: Length of @s buffer * Returns: 1 if signature is valid, 0 if signature is invalid, or -1 on failure */ int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *r, size_t r_len, const u8 *s, size_t s_len); /** * crypto_ec_key_group - Get IANA group identifier for an EC key * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen() * Returns: IANA group identifier and -1 on failure */ int crypto_ec_key_group(struct crypto_ec_key *key); /** * crypto_ec_key_cmp - Compare two EC public keys * @key1: Key 1 * @key2: Key 2 * Returns: 0 if public keys are identical, -1 otherwise */ int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2); /** * crypto_ec_key_debug_print - Dump EC key to debug log * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen() * @title: Name of the EC point in the trace */ void crypto_ec_key_debug_print(const struct crypto_ec_key *key, const char *title); /** * struct crypto_csr - Certification Signing Request * * Internal data structure for CSR. The contents is specific to the used * crypto library. * For now it is assumed that only an EC public key can be used */ struct crypto_csr; /** * enum crypto_csr_name - CSR name type */ enum crypto_csr_name { CSR_NAME_CN, CSR_NAME_SN, CSR_NAME_C, CSR_NAME_O, CSR_NAME_OU, }; /** * enum crypto_csr_attr - CSR attribute */ enum crypto_csr_attr { CSR_ATTR_CHALLENGE_PASSWORD, }; /** * crypto_csr_init - Initialize empty CSR * Returns: Pointer to CSR data or %NULL on failure */ struct crypto_csr * crypto_csr_init(void); /** * crypto_csr_verify - Initialize CSR from CertificationRequest * @req: DER encoding of ASN.1 CertificationRequest * * Returns: Pointer to CSR data or %NULL on failure or if signature is invalid */ struct crypto_csr * crypto_csr_verify(const struct wpabuf *req); /** * crypto_csr_deinit - Free CSR structure * @csr: CSR structure from @crypto_csr_init() or crypto_csr_verify() */ void crypto_csr_deinit(struct crypto_csr *csr); /** * crypto_csr_set_ec_public_key - Set public key in CSR * @csr: CSR structure from @crypto_csr_init() * @key: EC public key to set as public key in the CSR * Returns: 0 on success, -1 on failure */ int crypto_csr_set_ec_public_key(struct crypto_csr *csr, struct crypto_ec_key *key); /** * crypto_csr_set_name - Set name entry in CSR SubjectName * @csr: CSR structure from @crypto_csr_init() * @type: Name type to add into the CSR SubjectName * @name: UTF-8 string to write in the CSR SubjectName * Returns: 0 on success, -1 on failure */ int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type, const char *name); /** * crypto_csr_set_attribute - Set attribute in CSR * @csr: CSR structure from @crypto_csr_init() * @attr: Attribute identifier * @attr_type: ASN.1 type of @value buffer * @value: Attribute value * @len: length of @value buffer * Returns: 0 on success, -1 on failure */ int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, int attr_type, const u8 *value, size_t len); /** * crypto_csr_get_attribute - Get attribute from CSR * @csr: CSR structure from @crypto_csr_verify() * @attr: Updated with atribute identifier * @len: Updated with length of returned buffer * @type: ASN.1 type of the attribute buffer * Returns: Type, length, and pointer on attribute value or %NULL on failure */ const u8 * crypto_csr_get_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, size_t *len, int *type); /** * crypto_csr_sign - Sign CSR and return ASN.1 CertificationRequest * @csr: CSR structure from @crypto_csr_init() * @key: Private key to sign the CSR (for now ony EC key are supported) * @algo: Hash algorithm to use for the signature * Returns: DER encoding of ASN.1 CertificationRequest for the CSR or %NULL on * failure */ struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, struct crypto_ec_key *key, enum crypto_hash_alg algo); #endif /* CRYPTO_H */ diff --git a/contrib/wpa/src/crypto/crypto_openssl.c b/contrib/wpa/src/crypto/crypto_openssl.c index ef669c408474..82c85762d84f 100644 --- a/contrib/wpa/src/crypto/crypto_openssl.c +++ b/contrib/wpa/src/crypto/crypto_openssl.c @@ -1,3213 +1,3244 @@ /* * Wrapper functions for OpenSSL libcrypto * Copyright (c) 2004-2017, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #ifdef CONFIG_OPENSSL_CMAC #include #endif /* CONFIG_OPENSSL_CMAC */ #ifdef CONFIG_ECC #include #include #include #endif /* CONFIG_ECC */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif /* OpenSSL version >= 3.0 */ #include "common.h" #include "utils/const_time.h" #include "wpabuf.h" #include "dh_group5.h" #include "sha1.h" #include "sha256.h" #include "sha384.h" #include "sha512.h" #include "md5.h" #include "aes_wrap.h" #include "crypto.h" #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) /* Compatibility wrappers for older versions. */ static HMAC_CTX * HMAC_CTX_new(void) { HMAC_CTX *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx) HMAC_CTX_init(ctx); return ctx; } static void HMAC_CTX_free(HMAC_CTX *ctx) { if (!ctx) return; HMAC_CTX_cleanup(ctx); bin_clear_free(ctx, sizeof(*ctx)); } static EVP_MD_CTX * EVP_MD_CTX_new(void) { EVP_MD_CTX *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx) EVP_MD_CTX_init(ctx); return ctx; } static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) { if (!ctx) return; EVP_MD_CTX_cleanup(ctx); bin_clear_free(ctx, sizeof(*ctx)); } #ifdef CONFIG_ECC static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { if (pkey->type != EVP_PKEY_EC) return NULL; return pkey->pkey.ec; } static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { sig->r = r; sig->s = s; return 1; } static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { if (pr) *pr = sig->r; if (ps) *ps = sig->s; } #endif /* CONFIG_ECC */ static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x) { return ASN1_STRING_data((ASN1_STRING *) x); } #endif /* OpenSSL version < 1.1.0 */ + +void openssl_load_legacy_provider(void) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + static bool loaded = false; + OSSL_PROVIDER *legacy; + + if (loaded) + return; + + legacy = OSSL_PROVIDER_load(NULL, "legacy"); + + if (legacy) { + OSSL_PROVIDER_load(NULL, "default"); + loaded = true; + } +#endif /* OpenSSL version >= 3.0 */ +} + + static BIGNUM * get_group5_prime(void) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !(defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) return BN_get_rfc3526_prime_1536(NULL); #elif !defined(OPENSSL_IS_BORINGSSL) return get_rfc3526_prime_1536(NULL); #else static const unsigned char RFC3526_PRIME_1536[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); #endif } static BIGNUM * get_group5_order(void) { static const unsigned char RFC3526_ORDER_1536[] = { 0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x87,0xED,0x51, 0x10,0xB4,0x61,0x1A,0x62,0x63,0x31,0x45,0xC0,0x6E,0x0E,0x68, 0x94,0x81,0x27,0x04,0x45,0x33,0xE6,0x3A,0x01,0x05,0xDF,0x53, 0x1D,0x89,0xCD,0x91,0x28,0xA5,0x04,0x3C,0xC7,0x1A,0x02,0x6E, 0xF7,0xCA,0x8C,0xD9,0xE6,0x9D,0x21,0x8D,0x98,0x15,0x85,0x36, 0xF9,0x2F,0x8A,0x1B,0xA7,0xF0,0x9A,0xB6,0xB6,0xA8,0xE1,0x22, 0xF2,0x42,0xDA,0xBB,0x31,0x2F,0x3F,0x63,0x7A,0x26,0x21,0x74, 0xD3,0x1B,0xF6,0xB5,0x85,0xFF,0xAE,0x5B,0x7A,0x03,0x5B,0xF6, 0xF7,0x1C,0x35,0xFD,0xAD,0x44,0xCF,0xD2,0xD7,0x4F,0x92,0x08, 0xBE,0x25,0x8F,0xF3,0x24,0x94,0x33,0x28,0xF6,0x72,0x2D,0x9E, 0xE1,0x00,0x3E,0x5C,0x50,0xB1,0xDF,0x82,0xCC,0x6D,0x24,0x1B, 0x0E,0x2A,0xE9,0xCD,0x34,0x8B,0x1F,0xD4,0x7E,0x92,0x67,0xAF, 0xC1,0xB2,0xAE,0x91,0xEE,0x51,0xD6,0xCB,0x0E,0x31,0x79,0xAB, 0x10,0x42,0xA9,0x5D,0xCF,0x6A,0x94,0x83,0xB8,0x4B,0x4B,0x36, 0xB3,0x86,0x1A,0xA7,0x25,0x5E,0x4C,0x02,0x78,0xBA,0x36,0x04, 0x65,0x11,0xB9,0x93,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF }; return BN_bin2bn(RFC3526_ORDER_1536, sizeof(RFC3526_ORDER_1536), NULL); } #ifdef OPENSSL_NO_SHA256 #define NO_SHA256_WRAPPER #endif #ifdef OPENSSL_NO_SHA512 #define NO_SHA384_WRAPPER #endif static int openssl_digest_vector(const EVP_MD *type, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { EVP_MD_CTX *ctx; size_t i; unsigned int mac_len; if (TEST_FAIL()) return -1; ctx = EVP_MD_CTX_new(); if (!ctx) return -1; if (!EVP_DigestInit_ex(ctx, type, NULL)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", ERR_error_string(ERR_get_error(), NULL)); EVP_MD_CTX_free(ctx); return -1; } for (i = 0; i < num_elem; i++) { if (!EVP_DigestUpdate(ctx, addr[i], len[i])) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " "failed: %s", ERR_error_string(ERR_get_error(), NULL)); EVP_MD_CTX_free(ctx); return -1; } } if (!EVP_DigestFinal(ctx, mac, &mac_len)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", ERR_error_string(ERR_get_error(), NULL)); EVP_MD_CTX_free(ctx); return -1; } EVP_MD_CTX_free(ctx); return 0; } #ifndef CONFIG_FIPS int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { + openssl_load_legacy_provider(); return openssl_digest_vector(EVP_md4(), num_elem, addr, len, mac); } #endif /* CONFIG_FIPS */ int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i, plen, ret = -1; EVP_CIPHER_CTX *ctx; + openssl_load_legacy_provider(); + /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; ctx = EVP_CIPHER_CTX_new(); if (ctx && EVP_EncryptInit_ex(ctx, EVP_des_ecb(), NULL, pkey, NULL) == 1 && EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && EVP_EncryptUpdate(ctx, cypher, &plen, clear, 8) == 1 && EVP_EncryptFinal_ex(ctx, &cypher[plen], &plen) == 1) ret = 0; else wpa_printf(MSG_ERROR, "OpenSSL: DES encrypt failed"); if (ctx) EVP_CIPHER_CTX_free(ctx); return ret; } #ifndef CONFIG_NO_RC4 int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { #ifdef OPENSSL_NO_RC4 return -1; #else /* OPENSSL_NO_RC4 */ EVP_CIPHER_CTX *ctx; int outl; int res = -1; unsigned char skip_buf[16]; + openssl_load_legacy_provider(); + ctx = EVP_CIPHER_CTX_new(); if (!ctx || !EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, NULL, NULL, 1) || !EVP_CIPHER_CTX_set_padding(ctx, 0) || !EVP_CIPHER_CTX_set_key_length(ctx, keylen) || !EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, 1)) goto out; while (skip >= sizeof(skip_buf)) { size_t len = skip; if (len > sizeof(skip_buf)) len = sizeof(skip_buf); if (!EVP_CipherUpdate(ctx, skip_buf, &outl, skip_buf, len)) goto out; skip -= len; } if (EVP_CipherUpdate(ctx, data, &outl, data, data_len)) res = 0; out: if (ctx) EVP_CIPHER_CTX_free(ctx); return res; #endif /* OPENSSL_NO_RC4 */ } #endif /* CONFIG_NO_RC4 */ #ifndef CONFIG_FIPS int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md5(), num_elem, addr, len, mac); } #endif /* CONFIG_FIPS */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha1(), num_elem, addr, len, mac); } #ifndef NO_SHA256_WRAPPER int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha256(), num_elem, addr, len, mac); } #endif /* NO_SHA256_WRAPPER */ #ifndef NO_SHA384_WRAPPER int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha384(), num_elem, addr, len, mac); } #endif /* NO_SHA384_WRAPPER */ #ifndef NO_SHA512_WRAPPER int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha512(), num_elem, addr, len, mac); } #endif /* NO_SHA512_WRAPPER */ static const EVP_CIPHER * aes_get_evp_cipher(size_t keylen) { switch (keylen) { case 16: return EVP_aes_128_ecb(); case 24: return EVP_aes_192_ecb(); case 32: return EVP_aes_256_ecb(); } return NULL; } void * aes_encrypt_init(const u8 *key, size_t len) { EVP_CIPHER_CTX *ctx; const EVP_CIPHER *type; if (TEST_FAIL()) return NULL; type = aes_get_evp_cipher(len); if (!type) { wpa_printf(MSG_INFO, "%s: Unsupported len=%u", __func__, (unsigned int) len); return NULL; } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return NULL; if (EVP_EncryptInit_ex(ctx, type, NULL, key, NULL) != 1) { os_free(ctx); return NULL; } EVP_CIPHER_CTX_set_padding(ctx, 0); return ctx; } int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { EVP_CIPHER_CTX *c = ctx; int clen = 16; if (EVP_EncryptUpdate(c, crypt, &clen, plain, 16) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0; } void aes_encrypt_deinit(void *ctx) { EVP_CIPHER_CTX *c = ctx; u8 buf[16]; int len = sizeof(buf); if (EVP_EncryptFinal_ex(c, buf, &len) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_EncryptFinal_ex failed: " "%s", ERR_error_string(ERR_get_error(), NULL)); } if (len != 0) { wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " "in AES encrypt", len); } EVP_CIPHER_CTX_free(c); } void * aes_decrypt_init(const u8 *key, size_t len) { EVP_CIPHER_CTX *ctx; const EVP_CIPHER *type; if (TEST_FAIL()) return NULL; type = aes_get_evp_cipher(len); if (!type) { wpa_printf(MSG_INFO, "%s: Unsupported len=%u", __func__, (unsigned int) len); return NULL; } ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) return NULL; if (EVP_DecryptInit_ex(ctx, type, NULL, key, NULL) != 1) { EVP_CIPHER_CTX_free(ctx); return NULL; } EVP_CIPHER_CTX_set_padding(ctx, 0); return ctx; } int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { EVP_CIPHER_CTX *c = ctx; int plen = 16; if (EVP_DecryptUpdate(c, plain, &plen, crypt, 16) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0; } void aes_decrypt_deinit(void *ctx) { EVP_CIPHER_CTX *c = ctx; u8 buf[16]; int len = sizeof(buf); if (EVP_DecryptFinal_ex(c, buf, &len) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DecryptFinal_ex failed: " "%s", ERR_error_string(ERR_get_error(), NULL)); } if (len != 0) { wpa_printf(MSG_ERROR, "OpenSSL: Unexpected padding length %d " "in AES decrypt", len); } EVP_CIPHER_CTX_free(c); } #ifndef CONFIG_FIPS #ifndef CONFIG_OPENSSL_INTERNAL_AES_WRAP int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) { AES_KEY actx; int res; if (TEST_FAIL()) return -1; if (AES_set_encrypt_key(kek, kek_len << 3, &actx)) return -1; res = AES_wrap_key(&actx, NULL, cipher, plain, n * 8); OPENSSL_cleanse(&actx, sizeof(actx)); return res <= 0 ? -1 : 0; } int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) { AES_KEY actx; int res; if (TEST_FAIL()) return -1; if (AES_set_decrypt_key(kek, kek_len << 3, &actx)) return -1; res = AES_unwrap_key(&actx, NULL, plain, cipher, (n + 1) * 8); OPENSSL_cleanse(&actx, sizeof(actx)); return res <= 0 ? -1 : 0; } #endif /* CONFIG_OPENSSL_INTERNAL_AES_WRAP */ #endif /* CONFIG_FIPS */ int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { EVP_CIPHER_CTX *ctx; int clen, len; u8 buf[16]; int res = -1; if (TEST_FAIL()) return -1; ctx = EVP_CIPHER_CTX_new(); if (!ctx) return -1; clen = data_len; len = sizeof(buf); if (EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 && EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && EVP_EncryptUpdate(ctx, data, &clen, data, data_len) == 1 && clen == (int) data_len && EVP_EncryptFinal_ex(ctx, buf, &len) == 1 && len == 0) res = 0; EVP_CIPHER_CTX_free(ctx); return res; } int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { EVP_CIPHER_CTX *ctx; int plen, len; u8 buf[16]; int res = -1; if (TEST_FAIL()) return -1; ctx = EVP_CIPHER_CTX_new(); if (!ctx) return -1; plen = data_len; len = sizeof(buf); if (EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv) == 1 && EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && EVP_DecryptUpdate(ctx, data, &plen, data, data_len) == 1 && plen == (int) data_len && EVP_DecryptFinal_ex(ctx, buf, &len) == 1 && len == 0) res = 0; EVP_CIPHER_CTX_free(ctx); return res; } int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, u8 *pubkey) { size_t pubkey_len, pad; if (os_get_random(privkey, prime_len) < 0) return -1; if (os_memcmp(privkey, prime, prime_len) > 0) { /* Make sure private value is smaller than prime */ privkey[0] = 0; } pubkey_len = prime_len; if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, pubkey, &pubkey_len) < 0) return -1; if (pubkey_len < prime_len) { pad = prime_len - pubkey_len; os_memmove(pubkey + pad, pubkey, pubkey_len); os_memset(pubkey, 0, pad); } return 0; } int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, const u8 *order, size_t order_len, const u8 *privkey, size_t privkey_len, const u8 *pubkey, size_t pubkey_len, u8 *secret, size_t *len) { BIGNUM *pub, *p; int res = -1; pub = BN_bin2bn(pubkey, pubkey_len, NULL); p = BN_bin2bn(prime, prime_len, NULL); if (!pub || !p || BN_is_zero(pub) || BN_is_one(pub) || BN_cmp(pub, p) >= 0) goto fail; if (order) { BN_CTX *ctx; BIGNUM *q, *tmp; int failed; /* verify: pubkey^q == 1 mod p */ q = BN_bin2bn(order, order_len, NULL); ctx = BN_CTX_new(); tmp = BN_new(); failed = !q || !ctx || !tmp || !BN_mod_exp(tmp, pub, q, p, ctx) || !BN_is_one(tmp); BN_clear_free(q); BN_clear_free(tmp); BN_CTX_free(ctx); if (failed) goto fail; } res = crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, prime, prime_len, secret, len); fail: BN_clear_free(pub); BN_clear_free(p); return res; } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; int ret = -1; BN_CTX *ctx; ctx = BN_CTX_new(); if (ctx == NULL) return -1; bn_base = BN_bin2bn(base, base_len, NULL); bn_exp = BN_bin2bn(power, power_len, NULL); bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); bn_result = BN_new(); if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || bn_result == NULL) goto error; if (BN_mod_exp_mont_consttime(bn_result, bn_base, bn_exp, bn_modulus, ctx, NULL) != 1) goto error; *result_len = BN_bn2bin(bn_result, result); ret = 0; error: BN_clear_free(bn_base); BN_clear_free(bn_exp); BN_clear_free(bn_modulus); BN_clear_free(bn_result); BN_CTX_free(ctx); return ret; } struct crypto_cipher { EVP_CIPHER_CTX *enc; EVP_CIPHER_CTX *dec; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; const EVP_CIPHER *cipher; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; switch (alg) { #ifndef CONFIG_NO_RC4 #ifndef OPENSSL_NO_RC4 case CRYPTO_CIPHER_ALG_RC4: cipher = EVP_rc4(); break; #endif /* OPENSSL_NO_RC4 */ #endif /* CONFIG_NO_RC4 */ #ifndef OPENSSL_NO_AES case CRYPTO_CIPHER_ALG_AES: switch (key_len) { case 16: cipher = EVP_aes_128_cbc(); break; #ifndef OPENSSL_IS_BORINGSSL case 24: cipher = EVP_aes_192_cbc(); break; #endif /* OPENSSL_IS_BORINGSSL */ case 32: cipher = EVP_aes_256_cbc(); break; default: os_free(ctx); return NULL; } break; #endif /* OPENSSL_NO_AES */ #ifndef OPENSSL_NO_DES case CRYPTO_CIPHER_ALG_3DES: cipher = EVP_des_ede3_cbc(); break; case CRYPTO_CIPHER_ALG_DES: cipher = EVP_des_cbc(); break; #endif /* OPENSSL_NO_DES */ #ifndef OPENSSL_NO_RC2 case CRYPTO_CIPHER_ALG_RC2: cipher = EVP_rc2_ecb(); break; #endif /* OPENSSL_NO_RC2 */ default: os_free(ctx); return NULL; } if (!(ctx->enc = EVP_CIPHER_CTX_new()) || !EVP_EncryptInit_ex(ctx->enc, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_padding(ctx->enc, 0) || !EVP_CIPHER_CTX_set_key_length(ctx->enc, key_len) || !EVP_EncryptInit_ex(ctx->enc, NULL, NULL, key, iv)) { if (ctx->enc) EVP_CIPHER_CTX_free(ctx->enc); os_free(ctx); return NULL; } if (!(ctx->dec = EVP_CIPHER_CTX_new()) || !EVP_DecryptInit_ex(ctx->dec, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_padding(ctx->dec, 0) || !EVP_CIPHER_CTX_set_key_length(ctx->dec, key_len) || !EVP_DecryptInit_ex(ctx->dec, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_free(ctx->enc); if (ctx->dec) EVP_CIPHER_CTX_free(ctx->dec); os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { int outl; if (!EVP_EncryptUpdate(ctx->enc, crypt, &outl, plain, len)) return -1; return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { int outl; outl = len; if (!EVP_DecryptUpdate(ctx->dec, plain, &outl, crypt, len)) return -1; return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { EVP_CIPHER_CTX_free(ctx->enc); EVP_CIPHER_CTX_free(ctx->dec); os_free(ctx); } void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; *priv = NULL; wpabuf_free(*publ); *publ = NULL; dh = DH_new(); if (dh == NULL) return NULL; dh->g = BN_new(); if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) goto err; dh->p = get_group5_prime(); if (dh->p == NULL) goto err; dh->q = get_group5_order(); if (!dh->q) goto err; if (DH_generate_key(dh) != 1) goto err; publen = BN_num_bytes(dh->pub_key); pubkey = wpabuf_alloc(publen); if (pubkey == NULL) goto err; privlen = BN_num_bytes(dh->priv_key); privkey = wpabuf_alloc(privlen); if (privkey == NULL) goto err; BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); *priv = privkey; *publ = pubkey; return dh; err: wpabuf_clear_free(pubkey); wpabuf_clear_free(privkey); DH_free(dh); return NULL; #else DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; BIGNUM *p, *g, *q; const BIGNUM *priv_key = NULL, *pub_key = NULL; *priv = NULL; wpabuf_free(*publ); *publ = NULL; dh = DH_new(); if (dh == NULL) return NULL; g = BN_new(); p = get_group5_prime(); q = get_group5_order(); if (!g || BN_set_word(g, 2) != 1 || !p || !q || DH_set0_pqg(dh, p, q, g) != 1) goto err; p = NULL; q = NULL; g = NULL; if (DH_generate_key(dh) != 1) goto err; DH_get0_key(dh, &pub_key, &priv_key); publen = BN_num_bytes(pub_key); pubkey = wpabuf_alloc(publen); if (!pubkey) goto err; privlen = BN_num_bytes(priv_key); privkey = wpabuf_alloc(privlen); if (!privkey) goto err; BN_bn2bin(pub_key, wpabuf_put(pubkey, publen)); BN_bn2bin(priv_key, wpabuf_put(privkey, privlen)); *priv = privkey; *publ = pubkey; return dh; err: BN_free(p); BN_free(q); BN_free(g); wpabuf_clear_free(pubkey); wpabuf_clear_free(privkey); DH_free(dh); return NULL; #endif } void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) DH *dh; dh = DH_new(); if (dh == NULL) return NULL; dh->g = BN_new(); if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) goto err; dh->p = get_group5_prime(); if (dh->p == NULL) goto err; dh->priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); if (dh->priv_key == NULL) goto err; dh->pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); if (dh->pub_key == NULL) goto err; if (DH_generate_key(dh) != 1) goto err; return dh; err: DH_free(dh); return NULL; #else DH *dh; BIGNUM *p = NULL, *g, *priv_key = NULL, *pub_key = NULL; dh = DH_new(); if (dh == NULL) return NULL; g = BN_new(); p = get_group5_prime(); if (!g || BN_set_word(g, 2) != 1 || !p || DH_set0_pqg(dh, p, NULL, g) != 1) goto err; p = NULL; g = NULL; priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL); pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL); if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1) goto err; pub_key = NULL; priv_key = NULL; if (DH_generate_key(dh) != 1) goto err; return dh; err: BN_free(p); BN_free(g); BN_free(pub_key); BN_clear_free(priv_key); DH_free(dh); return NULL; #endif } struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private) { BIGNUM *pub_key; struct wpabuf *res = NULL; size_t rlen; DH *dh = ctx; int keylen; if (ctx == NULL) return NULL; pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), NULL); if (pub_key == NULL) return NULL; rlen = DH_size(dh); res = wpabuf_alloc(rlen); if (res == NULL) goto err; keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); if (keylen < 0) goto err; wpabuf_put(res, keylen); BN_clear_free(pub_key); return res; err: BN_clear_free(pub_key); wpabuf_clear_free(res); return NULL; } void dh5_free(void *ctx) { DH *dh; if (ctx == NULL) return; dh = ctx; DH_free(dh); } struct crypto_hash { HMAC_CTX *ctx; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; const EVP_MD *md; switch (alg) { #ifndef OPENSSL_NO_MD5 case CRYPTO_HASH_ALG_HMAC_MD5: md = EVP_md5(); break; #endif /* OPENSSL_NO_MD5 */ #ifndef OPENSSL_NO_SHA case CRYPTO_HASH_ALG_HMAC_SHA1: md = EVP_sha1(); break; #endif /* OPENSSL_NO_SHA */ #ifndef OPENSSL_NO_SHA256 #ifdef CONFIG_SHA256 case CRYPTO_HASH_ALG_HMAC_SHA256: md = EVP_sha256(); break; #endif /* CONFIG_SHA256 */ #endif /* OPENSSL_NO_SHA256 */ default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->ctx = HMAC_CTX_new(); if (!ctx->ctx) { os_free(ctx); return NULL; } if (HMAC_Init_ex(ctx->ctx, key, key_len, md, NULL) != 1) { HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); return NULL; } return ctx; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL) return; HMAC_Update(ctx->ctx, data, len); } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { unsigned int mdlen; int res; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) { HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); return 0; } mdlen = *len; res = HMAC_Final(ctx->ctx, mac, &mdlen); HMAC_CTX_free(ctx->ctx); bin_clear_free(ctx, sizeof(*ctx)); if (TEST_FAIL()) return -1; if (res == 1) { *len = mdlen; return 0; } return -1; } static int openssl_hmac_vector(const EVP_MD *type, const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac, unsigned int mdlen) { HMAC_CTX *ctx; size_t i; int res; if (TEST_FAIL()) return -1; ctx = HMAC_CTX_new(); if (!ctx) return -1; res = HMAC_Init_ex(ctx, key, key_len, type, NULL); if (res != 1) goto done; for (i = 0; i < num_elem; i++) HMAC_Update(ctx, addr[i], len[i]); res = HMAC_Final(ctx, mac, &mdlen); done: HMAC_CTX_free(ctx); return res == 1 ? 0 : -1; } #ifndef CONFIG_FIPS int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len, mac, 16); } int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_FIPS */ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen) { if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, os_strlen(passphrase), ssid, ssid_len, iterations, buflen, buf) != 1) return -1; return 0; } int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_hmac_vector(EVP_sha1(), key, key_len, num_elem, addr, len, mac, 20); } int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); } #ifdef CONFIG_SHA256 int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_hmac_vector(EVP_sha256(), key, key_len, num_elem, addr, len, mac, 32); } int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_SHA256 */ #ifdef CONFIG_SHA384 int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_hmac_vector(EVP_sha384(), key, key_len, num_elem, addr, len, mac, 48); } int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_SHA384 */ #ifdef CONFIG_SHA512 int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_hmac_vector(EVP_sha512(), key, key_len, num_elem, addr, len, mac, 64); } int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_SHA512 */ int crypto_get_random(void *buf, size_t len) { if (RAND_bytes(buf, len) != 1) return -1; return 0; } #ifdef CONFIG_OPENSSL_CMAC int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { CMAC_CTX *ctx; int ret = -1; size_t outlen, i; if (TEST_FAIL()) return -1; ctx = CMAC_CTX_new(); if (ctx == NULL) return -1; if (key_len == 32) { if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL)) goto fail; } else if (key_len == 16) { if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL)) goto fail; } else { goto fail; } for (i = 0; i < num_elem; i++) { if (!CMAC_Update(ctx, addr[i], len[i])) goto fail; } if (!CMAC_Final(ctx, mac, &outlen) || outlen != 16) goto fail; ret = 0; fail: CMAC_CTX_free(ctx); return ret; } int omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return omac1_aes_vector(key, 16, num_elem, addr, len, mac); } int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); } #endif /* CONFIG_OPENSSL_CMAC */ struct crypto_bignum * crypto_bignum_init(void) { if (TEST_FAIL()) return NULL; return (struct crypto_bignum *) BN_new(); } struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) { BIGNUM *bn; if (TEST_FAIL()) return NULL; bn = BN_bin2bn(buf, len, NULL); return (struct crypto_bignum *) bn; } struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) { BIGNUM *bn; if (TEST_FAIL()) return NULL; bn = BN_new(); if (!bn) return NULL; if (BN_set_word(bn, val) != 1) { BN_free(bn); return NULL; } return (struct crypto_bignum *) bn; } void crypto_bignum_deinit(struct crypto_bignum *n, int clear) { if (clear) BN_clear_free((BIGNUM *) n); else BN_free((BIGNUM *) n); } int crypto_bignum_to_bin(const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen) { int num_bytes, offset; if (TEST_FAIL()) return -1; if (padlen > buflen) return -1; if (padlen) { #ifdef OPENSSL_IS_BORINGSSL if (BN_bn2bin_padded(buf, padlen, (const BIGNUM *) a) == 0) return -1; return padlen; #else /* OPENSSL_IS_BORINGSSL */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) return BN_bn2binpad((const BIGNUM *) a, buf, padlen); #endif #endif } num_bytes = BN_num_bytes((const BIGNUM *) a); if ((size_t) num_bytes > buflen) return -1; if (padlen > (size_t) num_bytes) offset = padlen - num_bytes; else offset = 0; os_memset(buf, 0, offset); BN_bn2bin((const BIGNUM *) a, buf + offset); return num_bytes + offset; } int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) { if (TEST_FAIL()) return -1; return BN_rand_range((BIGNUM *) r, (const BIGNUM *) m) == 1 ? 0 : -1; } int crypto_bignum_add(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { return BN_add((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ? 0 : -1; } int crypto_bignum_mod(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { int res; BN_CTX *bnctx; bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; res = BN_mod((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, bnctx); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_exptmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d) { int res; BN_CTX *bnctx; if (TEST_FAIL()) return -1; bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; res = BN_mod_exp_mont_consttime((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, (const BIGNUM *) c, bnctx, NULL); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_inverse(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { BIGNUM *res; BN_CTX *bnctx; if (TEST_FAIL()) return -1; bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; #ifdef OPENSSL_IS_BORINGSSL /* TODO: use BN_mod_inverse_blinded() ? */ #else /* OPENSSL_IS_BORINGSSL */ BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME); #endif /* OPENSSL_IS_BORINGSSL */ res = BN_mod_inverse((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, bnctx); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_sub(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { if (TEST_FAIL()) return -1; return BN_sub((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b) ? 0 : -1; } int crypto_bignum_div(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { int res; BN_CTX *bnctx; if (TEST_FAIL()) return -1; bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; #ifndef OPENSSL_IS_BORINGSSL BN_set_flags((BIGNUM *) a, BN_FLG_CONSTTIME); #endif /* OPENSSL_IS_BORINGSSL */ res = BN_div((BIGNUM *) c, NULL, (const BIGNUM *) a, (const BIGNUM *) b, bnctx); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_addmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d) { int res; BN_CTX *bnctx; if (TEST_FAIL()) return -1; bnctx = BN_CTX_new(); if (!bnctx) return -1; res = BN_mod_add((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, (const BIGNUM *) c, bnctx); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_mulmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d) { int res; BN_CTX *bnctx; if (TEST_FAIL()) return -1; bnctx = BN_CTX_new(); if (bnctx == NULL) return -1; res = BN_mod_mul((BIGNUM *) d, (const BIGNUM *) a, (const BIGNUM *) b, (const BIGNUM *) c, bnctx); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_sqrmod(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { int res; BN_CTX *bnctx; if (TEST_FAIL()) return -1; bnctx = BN_CTX_new(); if (!bnctx) return -1; res = BN_mod_sqr((BIGNUM *) c, (const BIGNUM *) a, (const BIGNUM *) b, bnctx); BN_CTX_free(bnctx); return res ? 0 : -1; } int crypto_bignum_rshift(const struct crypto_bignum *a, int n, struct crypto_bignum *r) { /* Note: BN_rshift() does not modify the first argument even though it * has not been marked const. */ return BN_rshift((BIGNUM *) a, (BIGNUM *) r, n) == 1 ? 0 : -1; } int crypto_bignum_cmp(const struct crypto_bignum *a, const struct crypto_bignum *b) { return BN_cmp((const BIGNUM *) a, (const BIGNUM *) b); } int crypto_bignum_is_zero(const struct crypto_bignum *a) { return BN_is_zero((const BIGNUM *) a); } int crypto_bignum_is_one(const struct crypto_bignum *a) { return BN_is_one((const BIGNUM *) a); } int crypto_bignum_is_odd(const struct crypto_bignum *a) { return BN_is_odd((const BIGNUM *) a); } int crypto_bignum_legendre(const struct crypto_bignum *a, const struct crypto_bignum *p) { BN_CTX *bnctx; BIGNUM *exp = NULL, *tmp = NULL; int res = -2; unsigned int mask; if (TEST_FAIL()) return -2; bnctx = BN_CTX_new(); if (bnctx == NULL) return -2; exp = BN_new(); tmp = BN_new(); if (!exp || !tmp || /* exp = (p-1) / 2 */ !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) || !BN_rshift1(exp, exp) || !BN_mod_exp_mont_consttime(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p, bnctx, NULL)) goto fail; /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need to use * constant time selection to avoid branches here. */ res = -1; mask = const_time_eq(BN_is_word(tmp, 1), 1); res = const_time_select_int(mask, 1, res); mask = const_time_eq(BN_is_zero(tmp), 1); res = const_time_select_int(mask, 0, res); fail: BN_clear_free(tmp); BN_clear_free(exp); BN_CTX_free(bnctx); return res; } #ifdef CONFIG_ECC struct crypto_ec { EC_GROUP *group; int nid; BN_CTX *bnctx; BIGNUM *prime; BIGNUM *order; BIGNUM *a; BIGNUM *b; }; static int crypto_ec_group_2_nid(int group) { /* Map from IANA registry for IKE D-H groups to OpenSSL NID */ switch (group) { case 19: return NID_X9_62_prime256v1; case 20: return NID_secp384r1; case 21: return NID_secp521r1; case 25: return NID_X9_62_prime192v1; case 26: return NID_secp224r1; #ifdef NID_brainpoolP224r1 case 27: return NID_brainpoolP224r1; #endif /* NID_brainpoolP224r1 */ #ifdef NID_brainpoolP256r1 case 28: return NID_brainpoolP256r1; #endif /* NID_brainpoolP256r1 */ #ifdef NID_brainpoolP384r1 case 29: return NID_brainpoolP384r1; #endif /* NID_brainpoolP384r1 */ #ifdef NID_brainpoolP512r1 case 30: return NID_brainpoolP512r1; #endif /* NID_brainpoolP512r1 */ default: return -1; } } struct crypto_ec * crypto_ec_init(int group) { struct crypto_ec *e; int nid; nid = crypto_ec_group_2_nid(group); if (nid < 0) return NULL; e = os_zalloc(sizeof(*e)); if (e == NULL) return NULL; e->nid = nid; e->bnctx = BN_CTX_new(); e->group = EC_GROUP_new_by_curve_name(nid); e->prime = BN_new(); e->order = BN_new(); e->a = BN_new(); e->b = BN_new(); if (e->group == NULL || e->bnctx == NULL || e->prime == NULL || e->order == NULL || e->a == NULL || e->b == NULL || !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) || !EC_GROUP_get_order(e->group, e->order, e->bnctx)) { crypto_ec_deinit(e); e = NULL; } return e; } void crypto_ec_deinit(struct crypto_ec *e) { if (e == NULL) return; BN_clear_free(e->b); BN_clear_free(e->a); BN_clear_free(e->order); BN_clear_free(e->prime); EC_GROUP_free(e->group); BN_CTX_free(e->bnctx); os_free(e); } struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e) { if (TEST_FAIL()) return NULL; if (e == NULL) return NULL; return (struct crypto_ec_point *) EC_POINT_new(e->group); } size_t crypto_ec_prime_len(struct crypto_ec *e) { return BN_num_bytes(e->prime); } size_t crypto_ec_prime_len_bits(struct crypto_ec *e) { return BN_num_bits(e->prime); } size_t crypto_ec_order_len(struct crypto_ec *e) { return BN_num_bytes(e->order); } const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e) { return (const struct crypto_bignum *) e->prime; } const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) { return (const struct crypto_bignum *) e->order; } const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) { return (const struct crypto_bignum *) e->a; } const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) { return (const struct crypto_bignum *) e->b; } const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e) { return (const struct crypto_ec_point *) EC_GROUP_get0_generator(e->group); } void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) { if (clear) EC_POINT_clear_free((EC_POINT *) p); else EC_POINT_free((EC_POINT *) p); } int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, struct crypto_bignum *x) { return EC_POINT_get_affine_coordinates_GFp(e->group, (const EC_POINT *) p, (BIGNUM *) x, NULL, e->bnctx) == 1 ? 0 : -1; } int crypto_ec_point_to_bin(struct crypto_ec *e, const struct crypto_ec_point *point, u8 *x, u8 *y) { BIGNUM *x_bn, *y_bn; int ret = -1; int len = BN_num_bytes(e->prime); if (TEST_FAIL()) return -1; x_bn = BN_new(); y_bn = BN_new(); if (x_bn && y_bn && EC_POINT_get_affine_coordinates_GFp(e->group, (EC_POINT *) point, x_bn, y_bn, e->bnctx)) { if (x) { crypto_bignum_to_bin((struct crypto_bignum *) x_bn, x, len, len); } if (y) { crypto_bignum_to_bin((struct crypto_bignum *) y_bn, y, len, len); } ret = 0; } BN_clear_free(x_bn); BN_clear_free(y_bn); return ret; } struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, const u8 *val) { BIGNUM *x, *y; EC_POINT *elem; int len = BN_num_bytes(e->prime); if (TEST_FAIL()) return NULL; x = BN_bin2bn(val, len, NULL); y = BN_bin2bn(val + len, len, NULL); elem = EC_POINT_new(e->group); if (x == NULL || y == NULL || elem == NULL) { BN_clear_free(x); BN_clear_free(y); EC_POINT_clear_free(elem); return NULL; } if (!EC_POINT_set_affine_coordinates_GFp(e->group, elem, x, y, e->bnctx)) { EC_POINT_clear_free(elem); elem = NULL; } BN_clear_free(x); BN_clear_free(y); return (struct crypto_ec_point *) elem; } int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b, struct crypto_ec_point *c) { if (TEST_FAIL()) return -1; return EC_POINT_add(e->group, (EC_POINT *) c, (const EC_POINT *) a, (const EC_POINT *) b, e->bnctx) ? 0 : -1; } int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, const struct crypto_bignum *b, struct crypto_ec_point *res) { if (TEST_FAIL()) return -1; return EC_POINT_mul(e->group, (EC_POINT *) res, NULL, (const EC_POINT *) p, (const BIGNUM *) b, e->bnctx) ? 0 : -1; } int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) { if (TEST_FAIL()) return -1; return EC_POINT_invert(e->group, (EC_POINT *) p, e->bnctx) ? 0 : -1; } -int crypto_ec_point_solve_y_coord(struct crypto_ec *e, - struct crypto_ec_point *p, - const struct crypto_bignum *x, int y_bit) -{ - if (TEST_FAIL()) - return -1; - if (!EC_POINT_set_compressed_coordinates_GFp(e->group, (EC_POINT *) p, - (const BIGNUM *) x, y_bit, - e->bnctx) || - !EC_POINT_is_on_curve(e->group, (EC_POINT *) p, e->bnctx)) - return -1; - return 0; -} - - struct crypto_bignum * crypto_ec_point_compute_y_sqr(struct crypto_ec *e, const struct crypto_bignum *x) { - BIGNUM *tmp, *tmp2, *y_sqr = NULL; + BIGNUM *tmp; if (TEST_FAIL()) return NULL; tmp = BN_new(); - tmp2 = BN_new(); - /* y^2 = x^3 + ax + b */ - if (tmp && tmp2 && + /* y^2 = x^3 + ax + b = (x^2 + a)x + b */ + if (tmp && BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) && + BN_mod_add_quick(tmp, e->a, tmp, e->prime) && BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) && - BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) && - BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) && - BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) { - y_sqr = tmp2; - tmp2 = NULL; - } + BN_mod_add_quick(tmp, tmp, e->b, e->prime)) + return (struct crypto_bignum *) tmp; BN_clear_free(tmp); - BN_clear_free(tmp2); - - return (struct crypto_bignum *) y_sqr; + return NULL; } int crypto_ec_point_is_at_infinity(struct crypto_ec *e, const struct crypto_ec_point *p) { return EC_POINT_is_at_infinity(e->group, (const EC_POINT *) p); } int crypto_ec_point_is_on_curve(struct crypto_ec *e, const struct crypto_ec_point *p) { return EC_POINT_is_on_curve(e->group, (const EC_POINT *) p, e->bnctx) == 1; } int crypto_ec_point_cmp(const struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b) { return EC_POINT_cmp(e->group, (const EC_POINT *) a, (const EC_POINT *) b, e->bnctx); } void crypto_ec_point_debug_print(const struct crypto_ec *e, const struct crypto_ec_point *p, const char *title) { BIGNUM *x, *y; char *x_str = NULL, *y_str = NULL; x = BN_new(); y = BN_new(); if (!x || !y || EC_POINT_get_affine_coordinates_GFp(e->group, (const EC_POINT *) p, x, y, e->bnctx) != 1) goto fail; x_str = BN_bn2hex(x); y_str = BN_bn2hex(y); if (!x_str || !y_str) goto fail; wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); fail: OPENSSL_free(x_str); OPENSSL_free(y_str); BN_free(x); BN_free(y); } struct crypto_ecdh { struct crypto_ec *ec; EVP_PKEY *pkey; }; struct crypto_ecdh * crypto_ecdh_init(int group) { struct crypto_ecdh *ecdh; EVP_PKEY *params = NULL; EC_KEY *ec_params = NULL; EVP_PKEY_CTX *kctx = NULL; ecdh = os_zalloc(sizeof(*ecdh)); if (!ecdh) goto fail; ecdh->ec = crypto_ec_init(group); if (!ecdh->ec) goto fail; ec_params = EC_KEY_new_by_curve_name(ecdh->ec->nid); if (!ec_params) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC_KEY parameters"); goto fail; } EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); params = EVP_PKEY_new(); if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EVP_PKEY parameters"); goto fail; } kctx = EVP_PKEY_CTX_new(params, NULL); if (!kctx) goto fail; if (EVP_PKEY_keygen_init(kctx) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen_init failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } if (EVP_PKEY_keygen(kctx, &ecdh->pkey) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_keygen failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } done: EC_KEY_free(ec_params); EVP_PKEY_free(params); EVP_PKEY_CTX_free(kctx); return ecdh; fail: crypto_ecdh_deinit(ecdh); ecdh = NULL; goto done; } struct crypto_ecdh * crypto_ecdh_init2(int group, struct crypto_ec_key *own_key) { struct crypto_ecdh *ecdh; ecdh = os_zalloc(sizeof(*ecdh)); if (!ecdh) goto fail; ecdh->ec = crypto_ec_init(group); if (!ecdh->ec) goto fail; ecdh->pkey = EVP_PKEY_new(); if (!ecdh->pkey || EVP_PKEY_assign_EC_KEY(ecdh->pkey, EVP_PKEY_get1_EC_KEY((EVP_PKEY *) own_key)) != 1) goto fail; return ecdh; fail: crypto_ecdh_deinit(ecdh); return NULL; } struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) { struct wpabuf *buf = NULL; EC_KEY *eckey; const EC_POINT *pubkey; BIGNUM *x, *y = NULL; int len = BN_num_bytes(ecdh->ec->prime); int res; eckey = EVP_PKEY_get1_EC_KEY(ecdh->pkey); if (!eckey) return NULL; pubkey = EC_KEY_get0_public_key(eckey); if (!pubkey) return NULL; x = BN_new(); if (inc_y) { y = BN_new(); if (!y) goto fail; } buf = wpabuf_alloc(inc_y ? 2 * len : len); if (!x || !buf) goto fail; if (EC_POINT_get_affine_coordinates_GFp(ecdh->ec->group, pubkey, x, y, ecdh->ec->bnctx) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EC_POINT_get_affine_coordinates_GFp failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } res = crypto_bignum_to_bin((struct crypto_bignum *) x, wpabuf_put(buf, len), len, len); if (res < 0) goto fail; if (inc_y) { res = crypto_bignum_to_bin((struct crypto_bignum *) y, wpabuf_put(buf, len), len, len); if (res < 0) goto fail; } done: BN_clear_free(x); BN_clear_free(y); EC_KEY_free(eckey); return buf; fail: wpabuf_free(buf); buf = NULL; goto done; } struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, const u8 *key, size_t len) { BIGNUM *x, *y = NULL; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *peerkey = NULL; struct wpabuf *secret = NULL; size_t secret_len; EC_POINT *pub; EC_KEY *eckey = NULL; x = BN_bin2bn(key, inc_y ? len / 2 : len, NULL); pub = EC_POINT_new(ecdh->ec->group); if (!x || !pub) goto fail; if (inc_y) { y = BN_bin2bn(key + len / 2, len / 2, NULL); if (!y) goto fail; if (!EC_POINT_set_affine_coordinates_GFp(ecdh->ec->group, pub, x, y, ecdh->ec->bnctx)) { wpa_printf(MSG_ERROR, "OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } } else if (!EC_POINT_set_compressed_coordinates_GFp(ecdh->ec->group, pub, x, 0, ecdh->ec->bnctx)) { wpa_printf(MSG_ERROR, "OpenSSL: EC_POINT_set_compressed_coordinates_GFp failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } if (!EC_POINT_is_on_curve(ecdh->ec->group, pub, ecdh->ec->bnctx)) { wpa_printf(MSG_ERROR, "OpenSSL: ECDH peer public key is not on curve"); goto fail; } eckey = EC_KEY_new_by_curve_name(ecdh->ec->nid); if (!eckey || EC_KEY_set_public_key(eckey, pub) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EC_KEY_set_public_key failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } peerkey = EVP_PKEY_new(); if (!peerkey || EVP_PKEY_set1_EC_KEY(peerkey, eckey) != 1) goto fail; ctx = EVP_PKEY_CTX_new(ecdh->pkey, NULL); if (!ctx || EVP_PKEY_derive_init(ctx) != 1 || EVP_PKEY_derive_set_peer(ctx, peerkey) != 1 || EVP_PKEY_derive(ctx, NULL, &secret_len) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_derive(1) failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } secret = wpabuf_alloc(secret_len); if (!secret) goto fail; if (EVP_PKEY_derive(ctx, wpabuf_put(secret, 0), &secret_len) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_PKEY_derive(2) failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } if (secret->size != secret_len) wpa_printf(MSG_DEBUG, "OpenSSL: EVP_PKEY_derive(2) changed secret_len %d -> %d", (int) secret->size, (int) secret_len); wpabuf_put(secret, secret_len); done: BN_free(x); BN_free(y); EC_KEY_free(eckey); EC_POINT_free(pub); EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(peerkey); return secret; fail: wpabuf_free(secret); secret = NULL; goto done; } void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) { if (ecdh) { crypto_ec_deinit(ecdh->ec); EVP_PKEY_free(ecdh->pkey); os_free(ecdh); } } size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) { return crypto_ec_prime_len(ecdh->ec); } struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) { EVP_PKEY *pkey = NULL; EC_KEY *eckey; eckey = d2i_ECPrivateKey(NULL, &der, der_len); if (!eckey) { wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); pkey = EVP_PKEY_new(); if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { EC_KEY_free(eckey); goto fail; } return (struct crypto_ec_key *) pkey; fail: crypto_ec_key_deinit((struct crypto_ec_key *) pkey); return NULL; } struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) { EVP_PKEY *pkey; pkey = d2i_PUBKEY(NULL, &der, der_len); if (!pkey) { wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } /* Ensure this is an EC key */ if (!EVP_PKEY_get0_EC_KEY(pkey)) goto fail; return (struct crypto_ec_key *) pkey; fail: crypto_ec_key_deinit((struct crypto_ec_key *) pkey); return NULL; } struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x, const u8 *buf_y, size_t len) { EC_KEY *eckey = NULL; EVP_PKEY *pkey = NULL; EC_GROUP *ec_group = NULL; BN_CTX *ctx; EC_POINT *point = NULL; BIGNUM *x = NULL, *y = NULL; int nid; if (!buf_x || !buf_y) return NULL; nid = crypto_ec_group_2_nid(group); if (nid < 0) { wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group); return NULL; } ctx = BN_CTX_new(); if (!ctx) goto fail; ec_group = EC_GROUP_new_by_curve_name(nid); if (!ec_group) goto fail; x = BN_bin2bn(buf_x, len, NULL); y = BN_bin2bn(buf_y, len, NULL); point = EC_POINT_new(ec_group); if (!x || !y || !point) goto fail; if (!EC_POINT_set_affine_coordinates_GFp(ec_group, point, x, y, ctx)) { wpa_printf(MSG_ERROR, "OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } if (!EC_POINT_is_on_curve(ec_group, point, ctx) || EC_POINT_is_at_infinity(ec_group, point)) { wpa_printf(MSG_ERROR, "OpenSSL: Invalid point"); goto fail; } eckey = EC_KEY_new(); if (!eckey || EC_KEY_set_group(eckey, ec_group) != 1 || EC_KEY_set_public_key(eckey, point) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to set EC_KEY: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); pkey = EVP_PKEY_new(); if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY"); goto fail; } out: EC_GROUP_free(ec_group); BN_free(x); BN_free(y); EC_POINT_free(point); BN_CTX_free(ctx); return (struct crypto_ec_key *) pkey; fail: EC_KEY_free(eckey); EVP_PKEY_free(pkey); pkey = NULL; goto out; } struct crypto_ec_key * crypto_ec_key_set_pub_point(struct crypto_ec *ec, const struct crypto_ec_point *pub) { EC_KEY *eckey; EVP_PKEY *pkey = NULL; eckey = EC_KEY_new(); if (!eckey || EC_KEY_set_group(eckey, ec->group) != 1 || EC_KEY_set_public_key(eckey, (const EC_POINT *) pub) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to set EC_KEY: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); pkey = EVP_PKEY_new(); if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY"); goto fail; } out: return (struct crypto_ec_key *) pkey; fail: EVP_PKEY_free(pkey); EC_KEY_free(eckey); pkey = NULL; goto out; } struct crypto_ec_key * crypto_ec_key_gen(int group) { EVP_PKEY_CTX *kctx = NULL; EC_KEY *ec_params = NULL, *eckey; EVP_PKEY *params = NULL, *key = NULL; int nid; nid = crypto_ec_group_2_nid(group); if (nid < 0) { wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group); return NULL; } ec_params = EC_KEY_new_by_curve_name(nid); if (!ec_params) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC_KEY parameters"); goto fail; } EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); params = EVP_PKEY_new(); if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EVP_PKEY parameters"); goto fail; } kctx = EVP_PKEY_CTX_new(params, NULL); if (!kctx || EVP_PKEY_keygen_init(kctx) != 1 || EVP_PKEY_keygen(kctx, &key) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to generate EC key"); key = NULL; goto fail; } - eckey = EVP_PKEY_get0_EC_KEY(key); + eckey = EVP_PKEY_get1_EC_KEY(key); if (!eckey) { key = NULL; goto fail; } EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); + EC_KEY_free(eckey); fail: EC_KEY_free(ec_params); EVP_PKEY_free(params); EVP_PKEY_CTX_free(kctx); return (struct crypto_ec_key *) key; } void crypto_ec_key_deinit(struct crypto_ec_key *key) { EVP_PKEY_free((EVP_PKEY *) key); } #ifdef OPENSSL_IS_BORINGSSL /* BoringSSL version of i2d_PUBKEY() always outputs public EC key using * uncompressed form so define a custom function to export EC pubkey using * the compressed format that is explicitly required for some protocols. */ #include #include typedef struct { /* AlgorithmIdentifier ecPublicKey with optional parameters present * as an OID identifying the curve */ X509_ALGOR *alg; /* Compressed format public key per ANSI X9.63 */ ASN1_BIT_STRING *pub_key; } EC_COMP_PUBKEY; ASN1_SEQUENCE(EC_COMP_PUBKEY) = { ASN1_SIMPLE(EC_COMP_PUBKEY, alg, X509_ALGOR), ASN1_SIMPLE(EC_COMP_PUBKEY, pub_key, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(EC_COMP_PUBKEY); IMPLEMENT_ASN1_FUNCTIONS(EC_COMP_PUBKEY); #endif /* OPENSSL_IS_BORINGSSL */ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) { #ifdef OPENSSL_IS_BORINGSSL unsigned char *der = NULL; int der_len; const EC_KEY *eckey; struct wpabuf *ret = NULL; size_t len; const EC_GROUP *group; const EC_POINT *point; BN_CTX *ctx; EC_COMP_PUBKEY *pubkey = NULL; int nid; ctx = BN_CTX_new(); eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!ctx || !eckey) goto fail; group = EC_KEY_get0_group(eckey); point = EC_KEY_get0_public_key(eckey); if (!group || !point) goto fail; nid = EC_GROUP_get_curve_name(group); pubkey = EC_COMP_PUBKEY_new(); if (!pubkey || X509_ALGOR_set0(pubkey->alg, OBJ_nid2obj(EVP_PKEY_EC), V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) goto fail; len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, ctx); if (len == 0) goto fail; der = OPENSSL_malloc(len); if (!der) goto fail; len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, der, len, ctx); OPENSSL_free(pubkey->pub_key->data); pubkey->pub_key->data = der; der = NULL; pubkey->pub_key->length = len; /* No unused bits */ pubkey->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); pubkey->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; der_len = i2d_EC_COMP_PUBKEY(pubkey, &der); if (der_len <= 0) { wpa_printf(MSG_ERROR, "BoringSSL: Failed to build DER encoded public key"); goto fail; } ret = wpabuf_alloc_copy(der, der_len); fail: EC_COMP_PUBKEY_free(pubkey); OPENSSL_free(der); BN_CTX_free(ctx); return ret; #else /* OPENSSL_IS_BORINGSSL */ unsigned char *der = NULL; int der_len; struct wpabuf *buf; + EC_KEY *eckey; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY *tmp; +#endif /* OpenSSL version >= 3.0 */ + + eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key); + if (!eckey) + return NULL; /* For now, all users expect COMPRESSED form */ - EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key), - POINT_CONVERSION_COMPRESSED); + EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + tmp = EVP_PKEY_new(); + if (!tmp) + return NULL; + if (EVP_PKEY_set1_EC_KEY(tmp, eckey) != 1) { + EVP_PKEY_free(tmp); + return NULL; + } + key = (struct crypto_ec_key *) tmp; +#endif /* OpenSSL version >= 3.0 */ der_len = i2d_PUBKEY((EVP_PKEY *) key, &der); + EC_KEY_free(eckey); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY_free(tmp); +#endif /* OpenSSL version >= 3.0 */ if (der_len <= 0) { wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s", ERR_error_string(ERR_get_error(), NULL)); return NULL; } buf = wpabuf_alloc_copy(der, der_len); OPENSSL_free(der); return buf; #endif /* OPENSSL_IS_BORINGSSL */ } struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, bool include_pub) { EC_KEY *eckey; unsigned char *der = NULL; int der_len; struct wpabuf *buf; unsigned int key_flags; - eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); + eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key); if (!eckey) return NULL; key_flags = EC_KEY_get_enc_flags(eckey); if (include_pub) key_flags &= ~EC_PKEY_NO_PUBKEY; else key_flags |= EC_PKEY_NO_PUBKEY; EC_KEY_set_enc_flags(eckey, key_flags); EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); der_len = i2d_ECPrivateKey(eckey, &der); + EC_KEY_free(eckey); if (der_len <= 0) return NULL; buf = wpabuf_alloc_copy(der, der_len); OPENSSL_free(der); return buf; } struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key, int prefix) { int len, res; EC_KEY *eckey; struct wpabuf *buf; unsigned char *pos; eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key); if (!eckey) return NULL; EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); len = i2o_ECPublicKey(eckey, NULL); if (len <= 0) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to determine public key encoding length"); EC_KEY_free(eckey); return NULL; } buf = wpabuf_alloc(len); if (!buf) { EC_KEY_free(eckey); return NULL; } pos = wpabuf_put(buf, len); res = i2o_ECPublicKey(eckey, &pos); EC_KEY_free(eckey); if (res != len) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to encode public key (res=%d/%d)", res, len); wpabuf_free(buf); return NULL; } if (!prefix) { /* Remove 0x04 prefix if requested */ pos = wpabuf_mhead(buf); os_memmove(pos, pos + 1, len - 1); buf->used--; } return buf; } const struct crypto_ec_point * crypto_ec_key_get_public_key(struct crypto_ec_key *key) { - EC_KEY *eckey; + const EC_KEY *eckey; eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!eckey) return NULL; return (const struct crypto_ec_point *) EC_KEY_get0_public_key(eckey); } const struct crypto_bignum * crypto_ec_key_get_private_key(struct crypto_ec_key *key) { - EC_KEY *eckey; + const EC_KEY *eckey; eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!eckey) return NULL; return (const struct crypto_bignum *) EC_KEY_get0_private_key(eckey); } struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, size_t len) { EVP_PKEY_CTX *pkctx; struct wpabuf *sig_der; size_t sig_len; sig_len = EVP_PKEY_size((EVP_PKEY *) key); sig_der = wpabuf_alloc(sig_len); if (!sig_der) return NULL; pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL); if (!pkctx || EVP_PKEY_sign_init(pkctx) <= 0 || EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len, data, len) <= 0) { wpabuf_free(sig_der); sig_der = NULL; } else { wpabuf_put(sig_der, sig_len); } EVP_PKEY_CTX_free(pkctx); return sig_der; } struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, const u8 *data, size_t len) { const EC_GROUP *group; const EC_KEY *eckey; BIGNUM *prime = NULL; ECDSA_SIG *sig = NULL; const BIGNUM *r, *s; u8 *r_buf, *s_buf; struct wpabuf *buf; const unsigned char *p; int prime_len; buf = crypto_ec_key_sign(key, data, len); if (!buf) return NULL; /* Extract (r,s) from Ecdsa-Sig-Value */ eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!eckey) goto fail; group = EC_KEY_get0_group(eckey); prime = BN_new(); if (!prime || !group || !EC_GROUP_get_curve_GFp(group, prime, NULL, NULL, NULL)) goto fail; prime_len = BN_num_bytes(prime); p = wpabuf_head(buf); sig = d2i_ECDSA_SIG(NULL, &p, wpabuf_len(buf)); if (!sig) goto fail; ECDSA_SIG_get0(sig, &r, &s); /* Re-use wpabuf returned by crypto_ec_key_sign() */ buf->used = 0; r_buf = wpabuf_put(buf, prime_len); s_buf = wpabuf_put(buf, prime_len); if (crypto_bignum_to_bin((const struct crypto_bignum *) r, r_buf, prime_len, prime_len) < 0 || crypto_bignum_to_bin((const struct crypto_bignum *) s, s_buf, prime_len, prime_len) < 0) goto fail; out: BN_free(prime); ECDSA_SIG_free(sig); return buf; fail: wpabuf_clear_free(buf); buf = NULL; goto out; } int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *sig, size_t sig_len) { EVP_PKEY_CTX *pkctx; int ret; pkctx = EVP_PKEY_CTX_new((EVP_PKEY *) key, NULL); if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) { EVP_PKEY_CTX_free(pkctx); return -1; } ret = EVP_PKEY_verify(pkctx, sig, sig_len, data, len); EVP_PKEY_CTX_free(pkctx); if (ret == 1) return 1; /* signature ok */ if (ret == 0) return 0; /* incorrect signature */ return -1; } int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, const u8 *data, size_t len, const u8 *r, size_t r_len, const u8 *s, size_t s_len) { ECDSA_SIG *sig; BIGNUM *r_bn, *s_bn; unsigned char *der = NULL; int der_len; int ret = -1; r_bn = BN_bin2bn(r, r_len, NULL); s_bn = BN_bin2bn(s, s_len, NULL); sig = ECDSA_SIG_new(); if (!r_bn || !s_bn || !sig || ECDSA_SIG_set0(sig, r_bn, s_bn) != 1) goto fail; r_bn = NULL; s_bn = NULL; der_len = i2d_ECDSA_SIG(sig, &der); if (der_len <= 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Could not DER encode signature"); goto fail; } ret = crypto_ec_key_verify_signature(key, data, len, der, der_len); fail: OPENSSL_free(der); BN_free(r_bn); BN_free(s_bn); ECDSA_SIG_free(sig); return ret; } int crypto_ec_key_group(struct crypto_ec_key *key) { const EC_KEY *eckey; const EC_GROUP *group; int nid; eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key); if (!eckey) return -1; group = EC_KEY_get0_group(eckey); if (!group) return -1; nid = EC_GROUP_get_curve_name(group); switch (nid) { case NID_X9_62_prime256v1: return 19; case NID_secp384r1: return 20; case NID_secp521r1: return 21; #ifdef NID_brainpoolP256r1 case NID_brainpoolP256r1: return 28; #endif /* NID_brainpoolP256r1 */ #ifdef NID_brainpoolP384r1 case NID_brainpoolP384r1: return 29; #endif /* NID_brainpoolP384r1 */ #ifdef NID_brainpoolP512r1 case NID_brainpoolP512r1: return 30; #endif /* NID_brainpoolP512r1 */ } wpa_printf(MSG_ERROR, "OpenSSL: Unsupported curve (nid=%d) in EC key", nid); return -1; } int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2) { if (EVP_PKEY_cmp((EVP_PKEY *) key1, (EVP_PKEY *) key2) != 1) return -1; return 0; } void crypto_ec_key_debug_print(const struct crypto_ec_key *key, const char *title) { BIO *out; size_t rlen; char *txt; int res; out = BIO_new(BIO_s_mem()); if (!out) return; EVP_PKEY_print_private(out, (EVP_PKEY *) key, 0, NULL); rlen = BIO_ctrl_pending(out); txt = os_malloc(rlen + 1); if (txt) { res = BIO_read(out, txt, rlen); if (res > 0) { txt[res] = '\0'; wpa_printf(MSG_DEBUG, "%s: %s", title, txt); } os_free(txt); } BIO_free(out); } struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7) { #ifdef OPENSSL_IS_BORINGSSL CBS pkcs7_cbs; #else /* OPENSSL_IS_BORINGSSL */ PKCS7 *p7 = NULL; const unsigned char *p = wpabuf_head(pkcs7); #endif /* OPENSSL_IS_BORINGSSL */ STACK_OF(X509) *certs; int i, num; BIO *out = NULL; size_t rlen; struct wpabuf *pem = NULL; int res; #ifdef OPENSSL_IS_BORINGSSL certs = sk_X509_new_null(); if (!certs) goto fail; CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7)); if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { wpa_printf(MSG_INFO, "OpenSSL: Could not parse PKCS#7 object: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } #else /* OPENSSL_IS_BORINGSSL */ p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7)); if (!p7) { wpa_printf(MSG_INFO, "OpenSSL: Could not parse PKCS#7 object: %s", ERR_error_string(ERR_get_error(), NULL)); goto fail; } switch (OBJ_obj2nid(p7->type)) { case NID_pkcs7_signed: certs = p7->d.sign->cert; break; case NID_pkcs7_signedAndEnveloped: certs = p7->d.signed_and_enveloped->cert; break; default: certs = NULL; break; } #endif /* OPENSSL_IS_BORINGSSL */ if (!certs || ((num = sk_X509_num(certs)) == 0)) { wpa_printf(MSG_INFO, "OpenSSL: No certificates found in PKCS#7 object"); goto fail; } out = BIO_new(BIO_s_mem()); if (!out) goto fail; for (i = 0; i < num; i++) { X509 *cert = sk_X509_value(certs, i); PEM_write_bio_X509(out, cert); } rlen = BIO_ctrl_pending(out); pem = wpabuf_alloc(rlen); if (!pem) goto fail; res = BIO_read(out, wpabuf_put(pem, 0), rlen); if (res <= 0) { wpabuf_free(pem); pem = NULL; goto fail; } wpabuf_put(pem, res); fail: #ifdef OPENSSL_IS_BORINGSSL if (certs) sk_X509_pop_free(certs, X509_free); #else /* OPENSSL_IS_BORINGSSL */ PKCS7_free(p7); #endif /* OPENSSL_IS_BORINGSSL */ if (out) BIO_free_all(out); return pem; } struct crypto_csr * crypto_csr_init() { return (struct crypto_csr *)X509_REQ_new(); } struct crypto_csr * crypto_csr_verify(const struct wpabuf *req) { X509_REQ *csr; EVP_PKEY *pkey = NULL; const u8 *der = wpabuf_head(req); csr = d2i_X509_REQ(NULL, &der, wpabuf_len(req)); if (!csr) return NULL; pkey = X509_REQ_get_pubkey((X509_REQ *)csr); if (!pkey) goto fail; if (X509_REQ_verify((X509_REQ *)csr, pkey) != 1) goto fail; return (struct crypto_csr *)csr; fail: X509_REQ_free(csr); return NULL; } void crypto_csr_deinit(struct crypto_csr *csr) { X509_REQ_free((X509_REQ *)csr); } int crypto_csr_set_ec_public_key(struct crypto_csr *csr, struct crypto_ec_key *key) { if (!X509_REQ_set_pubkey((X509_REQ *)csr, (EVP_PKEY *)key)) return -1; return 0; } int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type, const char *name) { X509_NAME *n; int nid; switch (type) { case CSR_NAME_CN: nid = NID_commonName; break; case CSR_NAME_SN: nid = NID_surname; break; case CSR_NAME_C: nid = NID_countryName; break; case CSR_NAME_O: nid = NID_organizationName; break; case CSR_NAME_OU: nid = NID_organizationalUnitName; break; default: return -1; } n = X509_REQ_get_subject_name((X509_REQ *) csr); if (!n) return -1; #if OPENSSL_VERSION_NUMBER < 0x10100000L if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8, (unsigned char *) name, os_strlen(name), -1, 0)) return -1; #else if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_UTF8, (const unsigned char *) name, os_strlen(name), -1, 0)) return -1; #endif return 0; } int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, int attr_type, const u8 *value, size_t len) { int nid; switch (attr) { case CSR_ATTR_CHALLENGE_PASSWORD: nid = NID_pkcs9_challengePassword; break; default: return -1; } if (!X509_REQ_add1_attr_by_NID((X509_REQ *) csr, nid, attr_type, value, len)) return -1; return 0; } const u8 * crypto_csr_get_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, size_t *len, int *type) { X509_ATTRIBUTE *attrib; ASN1_TYPE *attrib_type; ASN1_STRING *data; int loc; int nid; switch (attr) { case CSR_ATTR_CHALLENGE_PASSWORD: nid = NID_pkcs9_challengePassword; break; default: return NULL; } loc = X509_REQ_get_attr_by_NID((X509_REQ *) csr, nid, -1); if (loc < 0) return NULL; attrib = X509_REQ_get_attr((X509_REQ *) csr, loc); if (!attrib) return NULL; attrib_type = X509_ATTRIBUTE_get0_type(attrib, 0); if (!attrib_type) return NULL; *type = ASN1_TYPE_get(attrib_type); data = X509_ATTRIBUTE_get0_data(attrib, 0, *type, NULL); if (!data) return NULL; *len = ASN1_STRING_length(data); return ASN1_STRING_get0_data(data); } struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, struct crypto_ec_key *key, enum crypto_hash_alg algo) { const EVP_MD *sign_md; struct wpabuf *buf; unsigned char *der = NULL; int der_len; switch (algo) { case CRYPTO_HASH_ALG_SHA256: sign_md = EVP_sha256(); break; case CRYPTO_HASH_ALG_SHA384: sign_md = EVP_sha384(); break; case CRYPTO_HASH_ALG_SHA512: sign_md = EVP_sha512(); break; default: return NULL; } if (!X509_REQ_sign((X509_REQ *) csr, (EVP_PKEY *) key, sign_md)) return NULL; der_len = i2d_X509_REQ((X509_REQ *) csr, &der); if (der_len < 0) return NULL; buf = wpabuf_alloc_copy(der, der_len); OPENSSL_free(der); return buf; } #endif /* CONFIG_ECC */ diff --git a/contrib/wpa/src/crypto/crypto_wolfssl.c b/contrib/wpa/src/crypto/crypto_wolfssl.c index 6f116eb62f53..00ecf61352a1 100644 --- a/contrib/wpa/src/crypto/crypto_wolfssl.c +++ b/contrib/wpa/src/crypto/crypto_wolfssl.c @@ -1,1849 +1,1825 @@ /* * Wrapper functions for libwolfssl * Copyright (c) 2004-2017, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" /* wolfSSL headers */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef CONFIG_FIPS int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { Md4 md4; size_t i; if (TEST_FAIL()) return -1; wc_InitMd4(&md4); for (i = 0; i < num_elem; i++) wc_Md4Update(&md4, addr[i], len[i]); wc_Md4Final(&md4, mac); return 0; } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { wc_Md5 md5; size_t i; if (TEST_FAIL()) return -1; wc_InitMd5(&md5); for (i = 0; i < num_elem; i++) wc_Md5Update(&md5, addr[i], len[i]); wc_Md5Final(&md5, mac); return 0; } #endif /* CONFIG_FIPS */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { wc_Sha sha; size_t i; if (TEST_FAIL()) return -1; wc_InitSha(&sha); for (i = 0; i < num_elem; i++) wc_ShaUpdate(&sha, addr[i], len[i]); wc_ShaFinal(&sha, mac); return 0; } #ifndef NO_SHA256_WRAPPER int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { wc_Sha256 sha256; size_t i; if (TEST_FAIL()) return -1; wc_InitSha256(&sha256); for (i = 0; i < num_elem; i++) wc_Sha256Update(&sha256, addr[i], len[i]); wc_Sha256Final(&sha256, mac); return 0; } #endif /* NO_SHA256_WRAPPER */ #ifdef CONFIG_SHA384 int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { wc_Sha384 sha384; size_t i; if (TEST_FAIL()) return -1; wc_InitSha384(&sha384); for (i = 0; i < num_elem; i++) wc_Sha384Update(&sha384, addr[i], len[i]); wc_Sha384Final(&sha384, mac); return 0; } #endif /* CONFIG_SHA384 */ #ifdef CONFIG_SHA512 int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { wc_Sha512 sha512; size_t i; if (TEST_FAIL()) return -1; wc_InitSha512(&sha512); for (i = 0; i < num_elem; i++) wc_Sha512Update(&sha512, addr[i], len[i]); wc_Sha512Final(&sha512, mac); return 0; } #endif /* CONFIG_SHA512 */ static int wolfssl_hmac_vector(int type, const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac, unsigned int mdlen) { Hmac hmac; size_t i; (void) mdlen; if (TEST_FAIL()) return -1; if (wc_HmacSetKey(&hmac, type, key, (word32) key_len) != 0) return -1; for (i = 0; i < num_elem; i++) if (wc_HmacUpdate(&hmac, addr[i], len[i]) != 0) return -1; if (wc_HmacFinal(&hmac, mac) != 0) return -1; return 0; } #ifndef CONFIG_FIPS int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return wolfssl_hmac_vector(WC_MD5, key, key_len, num_elem, addr, len, mac, 16); } int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_FIPS */ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return wolfssl_hmac_vector(WC_SHA, key, key_len, num_elem, addr, len, mac, 20); } int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); } #ifdef CONFIG_SHA256 int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return wolfssl_hmac_vector(WC_SHA256, key, key_len, num_elem, addr, len, mac, 32); } int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_SHA256 */ #ifdef CONFIG_SHA384 int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return wolfssl_hmac_vector(WC_SHA384, key, key_len, num_elem, addr, len, mac, 48); } int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_SHA384 */ #ifdef CONFIG_SHA512 int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return wolfssl_hmac_vector(WC_SHA512, key, key_len, num_elem, addr, len, mac, 64); } int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha512_vector(key, key_len, 1, &data, &data_len, mac); } #endif /* CONFIG_SHA512 */ int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen) { if (wc_PBKDF2(buf, (const byte*)passphrase, os_strlen(passphrase), ssid, ssid_len, iterations, buflen, WC_SHA) != 0) return -1; return 0; } #ifdef CONFIG_DES int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { Des des; u8 pkey[8], next, tmp; int i; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; wc_Des_SetKey(&des, pkey, NULL, DES_ENCRYPTION); wc_Des_EcbEncrypt(&des, cypher, clear, DES_BLOCK_SIZE); return 0; } #endif /* CONFIG_DES */ void * aes_encrypt_init(const u8 *key, size_t len) { Aes *aes; if (TEST_FAIL()) return NULL; aes = os_malloc(sizeof(Aes)); if (!aes) return NULL; if (wc_AesSetKey(aes, key, len, NULL, AES_ENCRYPTION) < 0) { os_free(aes); return NULL; } return aes; } int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { wc_AesEncryptDirect(ctx, crypt, plain); return 0; } void aes_encrypt_deinit(void *ctx) { os_free(ctx); } void * aes_decrypt_init(const u8 *key, size_t len) { Aes *aes; if (TEST_FAIL()) return NULL; aes = os_malloc(sizeof(Aes)); if (!aes) return NULL; if (wc_AesSetKey(aes, key, len, NULL, AES_DECRYPTION) < 0) { os_free(aes); return NULL; } return aes; } int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { wc_AesDecryptDirect(ctx, plain, crypt); return 0; } void aes_decrypt_deinit(void *ctx) { os_free(ctx); } int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { Aes aes; int ret; if (TEST_FAIL()) return -1; ret = wc_AesSetKey(&aes, key, 16, iv, AES_ENCRYPTION); if (ret != 0) return -1; ret = wc_AesCbcEncrypt(&aes, data, data, data_len); if (ret != 0) return -1; return 0; } int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { Aes aes; int ret; if (TEST_FAIL()) return -1; ret = wc_AesSetKey(&aes, key, 16, iv, AES_DECRYPTION); if (ret != 0) return -1; ret = wc_AesCbcDecrypt(&aes, data, data, data_len); if (ret != 0) return -1; return 0; } int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) { int ret; if (TEST_FAIL()) return -1; ret = wc_AesKeyWrap(kek, kek_len, plain, n * 8, cipher, (n + 1) * 8, NULL); return ret != (n + 1) * 8 ? -1 : 0; } int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) { int ret; if (TEST_FAIL()) return -1; ret = wc_AesKeyUnWrap(kek, kek_len, cipher, (n + 1) * 8, plain, n * 8, NULL); return ret != n * 8 ? -1 : 0; } #ifndef CONFIG_NO_RC4 int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { #ifndef NO_RC4 Arc4 arc4; unsigned char skip_buf[16]; wc_Arc4SetKey(&arc4, key, keylen); while (skip >= sizeof(skip_buf)) { size_t len = skip; if (len > sizeof(skip_buf)) len = sizeof(skip_buf); wc_Arc4Process(&arc4, skip_buf, skip_buf, len); skip -= len; } wc_Arc4Process(&arc4, data, data, data_len); return 0; #else /* NO_RC4 */ return -1; #endif /* NO_RC4 */ } #endif /* CONFIG_NO_RC4 */ #if defined(EAP_IKEV2) || defined(EAP_IKEV2_DYNAMIC) \ || defined(EAP_SERVER_IKEV2) union wolfssl_cipher { Aes aes; Des3 des3; Arc4 arc4; }; struct crypto_cipher { enum crypto_cipher_alg alg; union wolfssl_cipher enc; union wolfssl_cipher dec; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; ctx = os_zalloc(sizeof(*ctx)); if (!ctx) return NULL; switch (alg) { #ifndef CONFIG_NO_RC4 #ifndef NO_RC4 case CRYPTO_CIPHER_ALG_RC4: wc_Arc4SetKey(&ctx->enc.arc4, key, key_len); wc_Arc4SetKey(&ctx->dec.arc4, key, key_len); break; #endif /* NO_RC4 */ #endif /* CONFIG_NO_RC4 */ #ifndef NO_AES case CRYPTO_CIPHER_ALG_AES: switch (key_len) { case 16: case 24: case 32: break; default: os_free(ctx); return NULL; } if (wc_AesSetKey(&ctx->enc.aes, key, key_len, iv, AES_ENCRYPTION) || wc_AesSetKey(&ctx->dec.aes, key, key_len, iv, AES_DECRYPTION)) { os_free(ctx); return NULL; } break; #endif /* NO_AES */ #ifndef NO_DES3 case CRYPTO_CIPHER_ALG_3DES: if (key_len != DES3_KEYLEN || wc_Des3_SetKey(&ctx->enc.des3, key, iv, DES_ENCRYPTION) || wc_Des3_SetKey(&ctx->dec.des3, key, iv, DES_DECRYPTION)) { os_free(ctx); return NULL; } break; #endif /* NO_DES3 */ case CRYPTO_CIPHER_ALG_RC2: case CRYPTO_CIPHER_ALG_DES: default: os_free(ctx); return NULL; } ctx->alg = alg; return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { switch (ctx->alg) { #ifndef CONFIG_NO_RC4 #ifndef NO_RC4 case CRYPTO_CIPHER_ALG_RC4: wc_Arc4Process(&ctx->enc.arc4, crypt, plain, len); return 0; #endif /* NO_RC4 */ #endif /* CONFIG_NO_RC4 */ #ifndef NO_AES case CRYPTO_CIPHER_ALG_AES: if (wc_AesCbcEncrypt(&ctx->enc.aes, crypt, plain, len) != 0) return -1; return 0; #endif /* NO_AES */ #ifndef NO_DES3 case CRYPTO_CIPHER_ALG_3DES: if (wc_Des3_CbcEncrypt(&ctx->enc.des3, crypt, plain, len) != 0) return -1; return 0; #endif /* NO_DES3 */ default: return -1; } return -1; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { switch (ctx->alg) { #ifndef CONFIG_NO_RC4 #ifndef NO_RC4 case CRYPTO_CIPHER_ALG_RC4: wc_Arc4Process(&ctx->dec.arc4, plain, crypt, len); return 0; #endif /* NO_RC4 */ #endif /* CONFIG_NO_RC4 */ #ifndef NO_AES case CRYPTO_CIPHER_ALG_AES: if (wc_AesCbcDecrypt(&ctx->dec.aes, plain, crypt, len) != 0) return -1; return 0; #endif /* NO_AES */ #ifndef NO_DES3 case CRYPTO_CIPHER_ALG_3DES: if (wc_Des3_CbcDecrypt(&ctx->dec.des3, plain, crypt, len) != 0) return -1; return 0; #endif /* NO_DES3 */ default: return -1; } return -1; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { os_free(ctx); } #endif #ifdef CONFIG_WPS static const unsigned char RFC3526_PRIME_1536[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const unsigned char RFC3526_GENERATOR_1536[] = { 0x02 }; #define RFC3526_LEN sizeof(RFC3526_PRIME_1536) void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { WC_RNG rng; DhKey *ret = NULL; DhKey *dh = NULL; struct wpabuf *privkey = NULL; struct wpabuf *pubkey = NULL; word32 priv_sz, pub_sz; *priv = NULL; wpabuf_free(*publ); *publ = NULL; dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (!dh) return NULL; wc_InitDhKey(dh); if (wc_InitRng(&rng) != 0) { XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER); return NULL; } privkey = wpabuf_alloc(RFC3526_LEN); pubkey = wpabuf_alloc(RFC3526_LEN); if (!privkey || !pubkey) goto done; if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536)) != 0) goto done; if (wc_DhGenerateKeyPair(dh, &rng, wpabuf_mhead(privkey), &priv_sz, wpabuf_mhead(pubkey), &pub_sz) != 0) goto done; wpabuf_put(privkey, priv_sz); wpabuf_put(pubkey, pub_sz); ret = dh; *priv = privkey; *publ = pubkey; dh = NULL; privkey = NULL; pubkey = NULL; done: wpabuf_clear_free(pubkey); wpabuf_clear_free(privkey); if (dh) { wc_FreeDhKey(dh); XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER); } wc_FreeRng(&rng); return ret; } #ifdef CONFIG_WPS_NFC void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) { DhKey *ret = NULL; DhKey *dh; byte *secret; word32 secret_sz; dh = XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (!dh) return NULL; wc_InitDhKey(dh); secret = XMALLOC(RFC3526_LEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (!secret) goto done; if (wc_DhSetKey(dh, RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536)) != 0) goto done; if (wc_DhAgree(dh, secret, &secret_sz, wpabuf_head(priv), wpabuf_len(priv), RFC3526_GENERATOR_1536, sizeof(RFC3526_GENERATOR_1536)) != 0) goto done; if (secret_sz != wpabuf_len(publ) || os_memcmp(secret, wpabuf_head(publ), secret_sz) != 0) goto done; ret = dh; dh = NULL; done: if (dh) { wc_FreeDhKey(dh); XFREE(dh, NULL, DYNAMIC_TYPE_TMP_BUFFER); } XFREE(secret, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } #endif /* CONFIG_WPS_NFC */ struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private) { struct wpabuf *ret = NULL; struct wpabuf *secret; word32 secret_sz; secret = wpabuf_alloc(RFC3526_LEN); if (!secret) goto done; if (wc_DhAgree(ctx, wpabuf_mhead(secret), &secret_sz, wpabuf_head(own_private), wpabuf_len(own_private), wpabuf_head(peer_public), wpabuf_len(peer_public)) != 0) goto done; wpabuf_put(secret, secret_sz); ret = secret; secret = NULL; done: wpabuf_clear_free(secret); return ret; } void dh5_free(void *ctx) { if (!ctx) return; wc_FreeDhKey(ctx); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); } #endif /* CONFIG_WPS */ int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, u8 *pubkey) { int ret = -1; WC_RNG rng; DhKey *dh = NULL; word32 priv_sz, pub_sz; if (TEST_FAIL()) return -1; dh = os_malloc(sizeof(DhKey)); if (!dh) return -1; wc_InitDhKey(dh); if (wc_InitRng(&rng) != 0) { os_free(dh); return -1; } if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0) goto done; if (wc_DhGenerateKeyPair(dh, &rng, privkey, &priv_sz, pubkey, &pub_sz) != 0) goto done; if (priv_sz < prime_len) { size_t pad_sz = prime_len - priv_sz; os_memmove(privkey + pad_sz, privkey, priv_sz); os_memset(privkey, 0, pad_sz); } if (pub_sz < prime_len) { size_t pad_sz = prime_len - pub_sz; os_memmove(pubkey + pad_sz, pubkey, pub_sz); os_memset(pubkey, 0, pad_sz); } ret = 0; done: wc_FreeDhKey(dh); os_free(dh); wc_FreeRng(&rng); return ret; } int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, const u8 *order, size_t order_len, const u8 *privkey, size_t privkey_len, const u8 *pubkey, size_t pubkey_len, u8 *secret, size_t *len) { int ret = -1; DhKey *dh; word32 secret_sz; dh = os_malloc(sizeof(DhKey)); if (!dh) return -1; wc_InitDhKey(dh); if (wc_DhSetKey(dh, prime, prime_len, &generator, 1) != 0) goto done; if (wc_DhAgree(dh, secret, &secret_sz, privkey, privkey_len, pubkey, pubkey_len) != 0) goto done; *len = secret_sz; ret = 0; done: wc_FreeDhKey(dh); os_free(dh); return ret; } #ifdef CONFIG_FIPS int crypto_get_random(void *buf, size_t len) { int ret = 0; WC_RNG rng; if (wc_InitRng(&rng) != 0) return -1; if (wc_RNG_GenerateBlock(&rng, buf, len) != 0) ret = -1; wc_FreeRng(&rng); return ret; } #endif /* CONFIG_FIPS */ #if defined(EAP_PWD) || defined(EAP_SERVER_PWD) struct crypto_hash { Hmac hmac; int size; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ret = NULL; struct crypto_hash *hash; int type; hash = os_zalloc(sizeof(*hash)); if (!hash) goto done; switch (alg) { #ifndef NO_MD5 case CRYPTO_HASH_ALG_HMAC_MD5: hash->size = 16; type = WC_MD5; break; #endif /* NO_MD5 */ #ifndef NO_SHA case CRYPTO_HASH_ALG_HMAC_SHA1: type = WC_SHA; hash->size = 20; break; #endif /* NO_SHA */ #ifdef CONFIG_SHA256 #ifndef NO_SHA256 case CRYPTO_HASH_ALG_HMAC_SHA256: type = WC_SHA256; hash->size = 32; break; #endif /* NO_SHA256 */ #endif /* CONFIG_SHA256 */ default: goto done; } if (wc_HmacSetKey(&hash->hmac, type, key, key_len) != 0) goto done; ret = hash; hash = NULL; done: os_free(hash); return ret; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (!ctx) return; wc_HmacUpdate(&ctx->hmac, data, len); } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { int ret = 0; if (!ctx) return -2; if (!mac || !len) goto done; if (wc_HmacFinal(&ctx->hmac, mac) != 0) { ret = -1; goto done; } *len = ctx->size; ret = 0; done: bin_clear_free(ctx, sizeof(*ctx)); if (TEST_FAIL()) return -1; return ret; } #endif int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { Cmac cmac; size_t i; word32 sz; if (TEST_FAIL()) return -1; if (wc_InitCmac(&cmac, key, key_len, WC_CMAC_AES, NULL) != 0) return -1; for (i = 0; i < num_elem; i++) if (wc_CmacUpdate(&cmac, addr[i], len[i]) != 0) return -1; sz = AES_BLOCK_SIZE; if (wc_CmacFinal(&cmac, mac, &sz) != 0 || sz != AES_BLOCK_SIZE) return -1; return 0; } int omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return omac1_aes_vector(key, 16, num_elem, addr, len, mac); } int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); } struct crypto_bignum * crypto_bignum_init(void) { mp_int *a; if (TEST_FAIL()) return NULL; a = os_malloc(sizeof(*a)); if (!a || mp_init(a) != MP_OKAY) { os_free(a); a = NULL; } return (struct crypto_bignum *) a; } struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len) { mp_int *a; if (TEST_FAIL()) return NULL; a = (mp_int *) crypto_bignum_init(); if (!a) return NULL; if (mp_read_unsigned_bin(a, buf, len) != MP_OKAY) { os_free(a); a = NULL; } return (struct crypto_bignum *) a; } struct crypto_bignum * crypto_bignum_init_uint(unsigned int val) { mp_int *a; if (TEST_FAIL()) return NULL; a = (mp_int *) crypto_bignum_init(); if (!a) return NULL; if (mp_set_int(a, val) != MP_OKAY) { os_free(a); a = NULL; } return (struct crypto_bignum *) a; } void crypto_bignum_deinit(struct crypto_bignum *n, int clear) { if (!n) return; if (clear) mp_forcezero((mp_int *) n); mp_clear((mp_int *) n); os_free((mp_int *) n); } int crypto_bignum_to_bin(const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen) { int num_bytes, offset; if (TEST_FAIL()) return -1; if (padlen > buflen) return -1; num_bytes = (mp_count_bits((mp_int *) a) + 7) / 8; if ((size_t) num_bytes > buflen) return -1; if (padlen > (size_t) num_bytes) offset = padlen - num_bytes; else offset = 0; os_memset(buf, 0, offset); mp_to_unsigned_bin((mp_int *) a, buf + offset); return num_bytes + offset; } int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) { int ret = 0; WC_RNG rng; size_t len; u8 *buf; if (TEST_FAIL()) return -1; if (wc_InitRng(&rng) != 0) return -1; len = (mp_count_bits((mp_int *) m) + 7) / 8; buf = os_malloc(len); if (!buf || wc_RNG_GenerateBlock(&rng, buf, len) != 0 || mp_read_unsigned_bin((mp_int *) r, buf, len) != MP_OKAY || mp_mod((mp_int *) r, (mp_int *) m, (mp_int *) r) != 0) ret = -1; wc_FreeRng(&rng); bin_clear_free(buf, len); return ret; } int crypto_bignum_add(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *r) { return mp_add((mp_int *) a, (mp_int *) b, (mp_int *) r) == MP_OKAY ? 0 : -1; } int crypto_bignum_mod(const struct crypto_bignum *a, const struct crypto_bignum *m, struct crypto_bignum *r) { return mp_mod((mp_int *) a, (mp_int *) m, (mp_int *) r) == MP_OKAY ? 0 : -1; } int crypto_bignum_exptmod(const struct crypto_bignum *b, const struct crypto_bignum *e, const struct crypto_bignum *m, struct crypto_bignum *r) { if (TEST_FAIL()) return -1; return mp_exptmod((mp_int *) b, (mp_int *) e, (mp_int *) m, (mp_int *) r) == MP_OKAY ? 0 : -1; } int crypto_bignum_inverse(const struct crypto_bignum *a, const struct crypto_bignum *m, struct crypto_bignum *r) { if (TEST_FAIL()) return -1; return mp_invmod((mp_int *) a, (mp_int *) m, (mp_int *) r) == MP_OKAY ? 0 : -1; } int crypto_bignum_sub(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *r) { if (TEST_FAIL()) return -1; return mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) r) == MP_OKAY ? 0 : -1; } int crypto_bignum_div(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *d) { if (TEST_FAIL()) return -1; return mp_div((mp_int *) a, (mp_int *) b, (mp_int *) d, NULL) == MP_OKAY ? 0 : -1; } int crypto_bignum_addmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *c, struct crypto_bignum *d) { if (TEST_FAIL()) return -1; return mp_addmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) == MP_OKAY ? 0 : -1; } int crypto_bignum_mulmod(const struct crypto_bignum *a, const struct crypto_bignum *b, const struct crypto_bignum *m, struct crypto_bignum *d) { if (TEST_FAIL()) return -1; return mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) m, (mp_int *) d) == MP_OKAY ? 0 : -1; } int crypto_bignum_sqrmod(const struct crypto_bignum *a, const struct crypto_bignum *b, struct crypto_bignum *c) { if (TEST_FAIL()) return -1; return mp_sqrmod((mp_int *) a, (mp_int *) b, (mp_int *) c) == MP_OKAY ? 0 : -1; } int crypto_bignum_rshift(const struct crypto_bignum *a, int n, struct crypto_bignum *r) { if (mp_copy((mp_int *) a, (mp_int *) r) != MP_OKAY) return -1; mp_rshb((mp_int *) r, n); return 0; } int crypto_bignum_cmp(const struct crypto_bignum *a, const struct crypto_bignum *b) { return mp_cmp((mp_int *) a, (mp_int *) b); } int crypto_bignum_is_zero(const struct crypto_bignum *a) { return mp_iszero((mp_int *) a); } int crypto_bignum_is_one(const struct crypto_bignum *a) { return mp_isone((const mp_int *) a); } int crypto_bignum_is_odd(const struct crypto_bignum *a) { return mp_isodd((mp_int *) a); } int crypto_bignum_legendre(const struct crypto_bignum *a, const struct crypto_bignum *p) { mp_int t; int ret; int res = -2; if (TEST_FAIL()) return -2; if (mp_init(&t) != MP_OKAY) return -2; /* t = (p-1) / 2 */ ret = mp_sub_d((mp_int *) p, 1, &t); if (ret == MP_OKAY) mp_rshb(&t, 1); if (ret == MP_OKAY) ret = mp_exptmod((mp_int *) a, &t, (mp_int *) p, &t); if (ret == MP_OKAY) { if (mp_isone(&t)) res = 1; else if (mp_iszero(&t)) res = 0; else res = -1; } mp_clear(&t); return res; } #ifdef CONFIG_ECC int ecc_map(ecc_point *, mp_int *, mp_digit); int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *a, mp_int *modulus, mp_digit mp); struct crypto_ec { ecc_key key; mp_int a; mp_int prime; mp_int order; mp_digit mont_b; mp_int b; }; struct crypto_ec * crypto_ec_init(int group) { int built = 0; struct crypto_ec *e; int curve_id; /* Map from IANA registry for IKE D-H groups to OpenSSL NID */ switch (group) { case 19: curve_id = ECC_SECP256R1; break; case 20: curve_id = ECC_SECP384R1; break; case 21: curve_id = ECC_SECP521R1; break; case 25: curve_id = ECC_SECP192R1; break; case 26: curve_id = ECC_SECP224R1; break; #ifdef HAVE_ECC_BRAINPOOL case 27: curve_id = ECC_BRAINPOOLP224R1; break; case 28: curve_id = ECC_BRAINPOOLP256R1; break; case 29: curve_id = ECC_BRAINPOOLP384R1; break; case 30: curve_id = ECC_BRAINPOOLP512R1; break; #endif /* HAVE_ECC_BRAINPOOL */ default: return NULL; } e = os_zalloc(sizeof(*e)); if (!e) return NULL; if (wc_ecc_init(&e->key) != 0 || wc_ecc_set_curve(&e->key, 0, curve_id) != 0 || mp_init(&e->a) != MP_OKAY || mp_init(&e->prime) != MP_OKAY || mp_init(&e->order) != MP_OKAY || mp_init(&e->b) != MP_OKAY || mp_read_radix(&e->a, e->key.dp->Af, 16) != MP_OKAY || mp_read_radix(&e->b, e->key.dp->Bf, 16) != MP_OKAY || mp_read_radix(&e->prime, e->key.dp->prime, 16) != MP_OKAY || mp_read_radix(&e->order, e->key.dp->order, 16) != MP_OKAY || mp_montgomery_setup(&e->prime, &e->mont_b) != MP_OKAY) goto done; built = 1; done: if (!built) { crypto_ec_deinit(e); e = NULL; } return e; } void crypto_ec_deinit(struct crypto_ec* e) { if (!e) return; mp_clear(&e->b); mp_clear(&e->order); mp_clear(&e->prime); mp_clear(&e->a); wc_ecc_free(&e->key); os_free(e); } struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e) { if (TEST_FAIL()) return NULL; if (!e) return NULL; return (struct crypto_ec_point *) wc_ecc_new_point(); } size_t crypto_ec_prime_len(struct crypto_ec *e) { return (mp_count_bits(&e->prime) + 7) / 8; } size_t crypto_ec_prime_len_bits(struct crypto_ec *e) { return mp_count_bits(&e->prime); } size_t crypto_ec_order_len(struct crypto_ec *e) { return (mp_count_bits(&e->order) + 7) / 8; } const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e) { return (const struct crypto_bignum *) &e->prime; } const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e) { return (const struct crypto_bignum *) &e->order; } const struct crypto_bignum * crypto_ec_get_a(struct crypto_ec *e) { return (const struct crypto_bignum *) &e->a; } const struct crypto_bignum * crypto_ec_get_b(struct crypto_ec *e) { return (const struct crypto_bignum *) &e->b; } void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) { ecc_point *point = (ecc_point *) p; if (!p) return; if (clear) { mp_forcezero(point->x); mp_forcezero(point->y); mp_forcezero(point->z); } wc_ecc_del_point(point); } int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, struct crypto_bignum *x) { return mp_copy(((ecc_point *) p)->x, (mp_int *) x) == MP_OKAY ? 0 : -1; } int crypto_ec_point_to_bin(struct crypto_ec *e, const struct crypto_ec_point *point, u8 *x, u8 *y) { ecc_point *p = (ecc_point *) point; if (TEST_FAIL()) return -1; if (!mp_isone(p->z)) { if (ecc_map(p, &e->prime, e->mont_b) != MP_OKAY) return -1; } if (x) { if (crypto_bignum_to_bin((struct crypto_bignum *)p->x, x, e->key.dp->size, e->key.dp->size) <= 0) return -1; } if (y) { if (crypto_bignum_to_bin((struct crypto_bignum *) p->y, y, e->key.dp->size, e->key.dp->size) <= 0) return -1; } return 0; } struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, const u8 *val) { ecc_point *point = NULL; int loaded = 0; if (TEST_FAIL()) return NULL; point = wc_ecc_new_point(); if (!point) goto done; if (mp_read_unsigned_bin(point->x, val, e->key.dp->size) != MP_OKAY) goto done; val += e->key.dp->size; if (mp_read_unsigned_bin(point->y, val, e->key.dp->size) != MP_OKAY) goto done; mp_set(point->z, 1); loaded = 1; done: if (!loaded) { wc_ecc_del_point(point); point = NULL; } return (struct crypto_ec_point *) point; } int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b, struct crypto_ec_point *c) { mp_int mu; ecc_point *ta = NULL, *tb = NULL; ecc_point *pa = (ecc_point *) a, *pb = (ecc_point *) b; mp_int *modulus = &e->prime; int ret; if (TEST_FAIL()) return -1; ret = mp_init(&mu); if (ret != MP_OKAY) return -1; ret = mp_montgomery_calc_normalization(&mu, modulus); if (ret != MP_OKAY) { mp_clear(&mu); return -1; } if (!mp_isone(&mu)) { ta = wc_ecc_new_point(); if (!ta) { mp_clear(&mu); return -1; } tb = wc_ecc_new_point(); if (!tb) { wc_ecc_del_point(ta); mp_clear(&mu); return -1; } if (mp_mulmod(pa->x, &mu, modulus, ta->x) != MP_OKAY || mp_mulmod(pa->y, &mu, modulus, ta->y) != MP_OKAY || mp_mulmod(pa->z, &mu, modulus, ta->z) != MP_OKAY || mp_mulmod(pb->x, &mu, modulus, tb->x) != MP_OKAY || mp_mulmod(pb->y, &mu, modulus, tb->y) != MP_OKAY || mp_mulmod(pb->z, &mu, modulus, tb->z) != MP_OKAY) { ret = -1; goto end; } pa = ta; pb = tb; } ret = ecc_projective_add_point(pa, pb, (ecc_point *) c, &e->a, &e->prime, e->mont_b); if (ret != 0) { ret = -1; goto end; } if (ecc_map((ecc_point *) c, &e->prime, e->mont_b) != MP_OKAY) ret = -1; else ret = 0; end: wc_ecc_del_point(tb); wc_ecc_del_point(ta); mp_clear(&mu); return ret; } int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, const struct crypto_bignum *b, struct crypto_ec_point *res) { int ret; if (TEST_FAIL()) return -1; ret = wc_ecc_mulmod((mp_int *) b, (ecc_point *) p, (ecc_point *) res, &e->a, &e->prime, 1); return ret == 0 ? 0 : -1; } int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) { ecc_point *point = (ecc_point *) p; if (TEST_FAIL()) return -1; if (mp_sub(&e->prime, point->y, point->y) != MP_OKAY) return -1; return 0; } -int crypto_ec_point_solve_y_coord(struct crypto_ec *e, - struct crypto_ec_point *p, - const struct crypto_bignum *x, int y_bit) -{ - byte buf[1 + 2 * MAX_ECC_BYTES]; - int ret; - int prime_len = crypto_ec_prime_len(e); - - if (TEST_FAIL()) - return -1; - - buf[0] = y_bit ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; - ret = crypto_bignum_to_bin(x, buf + 1, prime_len, prime_len); - if (ret <= 0) - return -1; - ret = wc_ecc_import_point_der(buf, 1 + 2 * ret, e->key.idx, - (ecc_point *) p); - if (ret != 0) - return -1; - - return 0; -} - - struct crypto_bignum * crypto_ec_point_compute_y_sqr(struct crypto_ec *e, const struct crypto_bignum *x) { mp_int *y2 = NULL; mp_int t; int calced = 0; if (TEST_FAIL()) return NULL; if (mp_init(&t) != MP_OKAY) return NULL; y2 = (mp_int *) crypto_bignum_init(); if (!y2) goto done; if (mp_sqrmod((mp_int *) x, &e->prime, y2) != 0 || mp_mulmod((mp_int *) x, y2, &e->prime, y2) != 0 || mp_mulmod((mp_int *) x, &e->a, &e->prime, &t) != 0 || mp_addmod(y2, &t, &e->prime, y2) != 0 || mp_addmod(y2, &e->b, &e->prime, y2) != 0) goto done; calced = 1; done: if (!calced) { if (y2) { mp_clear(y2); os_free(y2); } mp_clear(&t); } return (struct crypto_bignum *) y2; } int crypto_ec_point_is_at_infinity(struct crypto_ec *e, const struct crypto_ec_point *p) { return wc_ecc_point_is_at_infinity((ecc_point *) p); } int crypto_ec_point_is_on_curve(struct crypto_ec *e, const struct crypto_ec_point *p) { return wc_ecc_is_point((ecc_point *) p, &e->a, &e->b, &e->prime) == MP_OKAY; } int crypto_ec_point_cmp(const struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b) { return wc_ecc_cmp_point((ecc_point *) a, (ecc_point *) b); } struct crypto_ecdh { struct crypto_ec *ec; }; struct crypto_ecdh * crypto_ecdh_init(int group) { struct crypto_ecdh *ecdh = NULL; WC_RNG rng; int ret; if (wc_InitRng(&rng) != 0) goto fail; ecdh = os_zalloc(sizeof(*ecdh)); if (!ecdh) goto fail; ecdh->ec = crypto_ec_init(group); if (!ecdh->ec) goto fail; ret = wc_ecc_make_key_ex(&rng, ecdh->ec->key.dp->size, &ecdh->ec->key, ecdh->ec->key.dp->id); if (ret < 0) goto fail; done: wc_FreeRng(&rng); return ecdh; fail: crypto_ecdh_deinit(ecdh); ecdh = NULL; goto done; } void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) { if (ecdh) { crypto_ec_deinit(ecdh->ec); os_free(ecdh); } } struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) { struct wpabuf *buf = NULL; int ret; int len = ecdh->ec->key.dp->size; buf = wpabuf_alloc(inc_y ? 2 * len : len); if (!buf) goto fail; ret = crypto_bignum_to_bin((struct crypto_bignum *) ecdh->ec->key.pubkey.x, wpabuf_put(buf, len), len, len); if (ret < 0) goto fail; if (inc_y) { ret = crypto_bignum_to_bin((struct crypto_bignum *) ecdh->ec->key.pubkey.y, wpabuf_put(buf, len), len, len); if (ret < 0) goto fail; } done: return buf; fail: wpabuf_free(buf); buf = NULL; goto done; } struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, const u8 *key, size_t len) { int ret; struct wpabuf *pubkey = NULL; struct wpabuf *secret = NULL; word32 key_len = ecdh->ec->key.dp->size; ecc_point *point = NULL; size_t need_key_len = inc_y ? 2 * key_len : key_len; if (len < need_key_len) goto fail; pubkey = wpabuf_alloc(1 + 2 * key_len); if (!pubkey) goto fail; wpabuf_put_u8(pubkey, inc_y ? ECC_POINT_UNCOMP : ECC_POINT_COMP_EVEN); wpabuf_put_data(pubkey, key, need_key_len); point = wc_ecc_new_point(); if (!point) goto fail; ret = wc_ecc_import_point_der(wpabuf_mhead(pubkey), 1 + 2 * key_len, ecdh->ec->key.idx, point); if (ret != MP_OKAY) goto fail; secret = wpabuf_alloc(key_len); if (!secret) goto fail; ret = wc_ecc_shared_secret_ex(&ecdh->ec->key, point, wpabuf_put(secret, key_len), &key_len); if (ret != MP_OKAY) goto fail; done: wc_ecc_del_point(point); wpabuf_free(pubkey); return secret; fail: wpabuf_free(secret); secret = NULL; goto done; } size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) { return crypto_ec_prime_len(ecdh->ec); } #endif /* CONFIG_ECC */ diff --git a/contrib/wpa/src/crypto/tls_openssl.c b/contrib/wpa/src/crypto/tls_openssl.c index 203b0f781ff5..c9e00b3af855 100644 --- a/contrib/wpa/src/crypto/tls_openssl.c +++ b/contrib/wpa/src/crypto/tls_openssl.c @@ -1,5761 +1,5775 @@ /* * SSL/TLS interface functions for OpenSSL * Copyright (c) 2004-2015, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" #ifndef CONFIG_SMARTCARD #ifndef OPENSSL_NO_ENGINE #ifndef ANDROID #define OPENSSL_NO_ENGINE #endif #endif #endif #include #include #include #include #include #ifndef OPENSSL_NO_ENGINE #include #endif /* OPENSSL_NO_ENGINE */ #ifndef OPENSSL_NO_DSA #include #endif #ifndef OPENSSL_NO_DH #include #endif #include "common.h" #include "crypto.h" #include "sha1.h" #include "sha256.h" #include "tls.h" #include "tls_openssl.h" #if !defined(CONFIG_FIPS) && \ (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ defined(EAP_SERVER_FAST)) #define OPENSSL_NEED_EAP_FAST_PRF #endif #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ defined(EAP_SERVER_FAST) || defined(EAP_TEAP) || \ defined(EAP_SERVER_TEAP) #define EAP_FAST_OR_TEAP #endif #if defined(OPENSSL_IS_BORINGSSL) /* stack_index_t is the return type of OpenSSL's sk_XXX_num() functions. */ typedef size_t stack_index_t; #else typedef int stack_index_t; #endif #ifdef SSL_set_tlsext_status_type #ifndef OPENSSL_NO_TLSEXT #define HAVE_OCSP #include #endif /* OPENSSL_NO_TLSEXT */ #endif /* SSL_set_tlsext_status_type */ #if (OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L)) && \ !defined(BORINGSSL_API_VERSION) /* * SSL_get_client_random() and SSL_get_server_random() were added in OpenSSL * 1.1.0 and newer BoringSSL revisions. Provide compatibility wrappers for * older versions. */ static size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen) { if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE) return 0; os_memcpy(out, ssl->s3->client_random, SSL3_RANDOM_SIZE); return SSL3_RANDOM_SIZE; } static size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen) { if (!ssl->s3 || outlen < SSL3_RANDOM_SIZE) return 0; os_memcpy(out, ssl->s3->server_random, SSL3_RANDOM_SIZE); return SSL3_RANDOM_SIZE; } #ifdef OPENSSL_NEED_EAP_FAST_PRF static size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen) { if (!session || session->master_key_length < 0 || (size_t) session->master_key_length > outlen) return 0; if ((size_t) session->master_key_length < outlen) outlen = session->master_key_length; os_memcpy(out, session->master_key, outlen); return outlen; } #endif /* OPENSSL_NEED_EAP_FAST_PRF */ #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) #ifdef CONFIG_SUITEB static int RSA_bits(const RSA *r) { return BN_num_bits(r->n); } #endif /* CONFIG_SUITEB */ static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x) { return ASN1_STRING_data((ASN1_STRING *) x); } #endif #ifdef ANDROID #include #include static BIO * BIO_from_keystore(const char *key) { BIO *bio = NULL; uint8_t *value = NULL; int length = keystore_get(key, strlen(key), &value); if (length != -1 && (bio = BIO_new(BIO_s_mem())) != NULL) BIO_write(bio, value, length); free(value); return bio; } static int tls_add_ca_from_keystore(X509_STORE *ctx, const char *key_alias) { BIO *bio = BIO_from_keystore(key_alias); STACK_OF(X509_INFO) *stack = NULL; stack_index_t i; if (bio) { stack = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); BIO_free(bio); } if (!stack) { wpa_printf(MSG_WARNING, "TLS: Failed to parse certificate: %s", key_alias); return -1; } for (i = 0; i < sk_X509_INFO_num(stack); ++i) { X509_INFO *info = sk_X509_INFO_value(stack, i); if (info->x509) X509_STORE_add_cert(ctx, info->x509); if (info->crl) X509_STORE_add_crl(ctx, info->crl); } sk_X509_INFO_pop_free(stack, X509_INFO_free); return 0; } static int tls_add_ca_from_keystore_encoded(X509_STORE *ctx, const char *encoded_key_alias) { int rc = -1; int len = os_strlen(encoded_key_alias); unsigned char *decoded_alias; if (len & 1) { wpa_printf(MSG_WARNING, "Invalid hex-encoded alias: %s", encoded_key_alias); return rc; } decoded_alias = os_malloc(len / 2 + 1); if (decoded_alias) { if (!hexstr2bin(encoded_key_alias, decoded_alias, len / 2)) { decoded_alias[len / 2] = '\0'; rc = tls_add_ca_from_keystore( ctx, (const char *) decoded_alias); } os_free(decoded_alias); } return rc; } #endif /* ANDROID */ static int tls_openssl_ref_count = 0; static int tls_ex_idx_session = -1; struct tls_context { void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); void *cb_ctx; int cert_in_cb; char *ocsp_stapling_response; }; static struct tls_context *tls_global = NULL; struct tls_data { SSL_CTX *ssl; unsigned int tls_session_lifetime; int check_crl; int check_crl_strict; char *ca_cert; unsigned int crl_reload_interval; struct os_reltime crl_last_reload; char *check_cert_subject; }; struct tls_connection { struct tls_context *context; struct tls_data *data; SSL_CTX *ssl_ctx; SSL *ssl; BIO *ssl_in, *ssl_out; #if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE) ENGINE *engine; /* functional reference to the engine */ EVP_PKEY *private_key; /* the private key if using engine */ #endif /* OPENSSL_NO_ENGINE */ char *subject_match, *altsubject_match, *suffix_match, *domain_match; char *check_cert_subject; int read_alerts, write_alerts, failed; tls_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; /* SessionTicket received from OpenSSL hello_extension_cb (server) */ u8 *session_ticket; size_t session_ticket_len; unsigned int ca_cert_verify:1; unsigned int cert_probe:1; unsigned int server_cert_only:1; unsigned int invalid_hb_used:1; unsigned int success_data:1; unsigned int client_hello_generated:1; unsigned int server:1; u8 srv_cert_hash[32]; unsigned int flags; X509 *peer_cert; X509 *peer_issuer; X509 *peer_issuer_issuer; char *peer_subject; /* peer subject info for authenticated peer */ unsigned char client_random[SSL3_RANDOM_SIZE]; unsigned char server_random[SSL3_RANDOM_SIZE]; u16 cipher_suite; int server_dh_prime_len; }; static struct tls_context * tls_context_new(const struct tls_config *conf) { struct tls_context *context = os_zalloc(sizeof(*context)); if (context == NULL) return NULL; if (conf) { context->event_cb = conf->event_cb; context->cb_ctx = conf->cb_ctx; context->cert_in_cb = conf->cert_in_cb; } return context; } #ifdef CONFIG_NO_STDOUT_DEBUG static void _tls_show_errors(void) { unsigned long err; while ((err = ERR_get_error())) { /* Just ignore the errors, since stdout is disabled */ } } #define tls_show_errors(l, f, t) _tls_show_errors() #else /* CONFIG_NO_STDOUT_DEBUG */ static void tls_show_errors(int level, const char *func, const char *txt) { unsigned long err; wpa_printf(level, "OpenSSL: %s - %s %s", func, txt, ERR_error_string(ERR_get_error(), NULL)); while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "OpenSSL: pending error: %s", ERR_error_string(err, NULL)); } } #endif /* CONFIG_NO_STDOUT_DEBUG */ static X509_STORE * tls_crl_cert_reload(const char *ca_cert, int check_crl) { int flags; X509_STORE *store; store = X509_STORE_new(); if (!store) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new certificate store", __func__); return NULL; } if (ca_cert && X509_STORE_load_locations(store, ca_cert, NULL) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); X509_STORE_free(store); return NULL; } flags = check_crl ? X509_V_FLAG_CRL_CHECK : 0; if (check_crl == 2) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(store, flags); return store; } #ifdef CONFIG_NATIVE_WINDOWS /* Windows CryptoAPI and access to certificate stores */ #include #ifdef __MINGW32_VERSION /* * MinGW does not yet include all the needed definitions for CryptoAPI, so * define here whatever extra is needed. */ #define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) #define CERT_STORE_READONLY_FLAG 0x00008000 #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 #endif /* __MINGW32_VERSION */ struct cryptoapi_rsa_data { const CERT_CONTEXT *cert; HCRYPTPROV crypt_prov; DWORD key_spec; BOOL free_crypt_prov; }; static void cryptoapi_error(const char *msg) { wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u", msg, (unsigned int) GetLastError()); } static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct cryptoapi_rsa_data *priv = (struct cryptoapi_rsa_data *) rsa->meth->app_data; HCRYPTHASH hash; DWORD hash_size, len, i; unsigned char *buf = NULL; int ret = 0; if (priv == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (padding != RSA_PKCS1_PADDING) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) { wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported", __func__); RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) { cryptoapi_error("CryptCreateHash failed"); return 0; } len = sizeof(hash_size); if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0)) { cryptoapi_error("CryptGetHashParam failed"); goto err; } if ((int) hash_size != flen) { wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)", (unsigned) hash_size, flen); RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); goto err; } if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) { cryptoapi_error("CryptSetHashParam failed"); goto err; } len = RSA_size(rsa); buf = os_malloc(len); if (buf == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) { cryptoapi_error("CryptSignHash failed"); goto err; } for (i = 0; i < len; i++) to[i] = buf[len - i - 1]; ret = len; err: os_free(buf); CryptDestroyHash(hash); return ret; } static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv) { if (priv == NULL) return; if (priv->crypt_prov && priv->free_crypt_prov) CryptReleaseContext(priv->crypt_prov, 0); if (priv->cert) CertFreeCertificateContext(priv->cert); os_free(priv); } static int cryptoapi_finish(RSA *rsa) { cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data); os_free((void *) rsa->meth); rsa->meth = NULL; return 1; } static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store) { HCERTSTORE cs; const CERT_CONTEXT *ret = NULL; cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, store | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY"); if (cs == NULL) { cryptoapi_error("Failed to open 'My system store'"); return NULL; } if (strncmp(name, "cert://", 7) == 0) { unsigned short wbuf[255]; MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255); ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, wbuf, NULL); } else if (strncmp(name, "hash://", 7) == 0) { CRYPT_HASH_BLOB blob; int len; const char *hash = name + 7; unsigned char *buf; len = os_strlen(hash) / 2; buf = os_malloc(len); if (buf && hexstr2bin(hash, buf, len) == 0) { blob.cbData = len; blob.pbData = buf; ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HASH, &blob, NULL); } os_free(buf); } CertCloseStore(cs, 0); return ret; } static int tls_cryptoapi_cert(SSL *ssl, const char *name) { X509 *cert = NULL; RSA *rsa = NULL, *pub_rsa; struct cryptoapi_rsa_data *priv; RSA_METHOD *rsa_meth; if (name == NULL || (strncmp(name, "cert://", 7) != 0 && strncmp(name, "hash://", 7) != 0)) return -1; priv = os_zalloc(sizeof(*priv)); rsa_meth = os_zalloc(sizeof(*rsa_meth)); if (priv == NULL || rsa_meth == NULL) { wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory " "for CryptoAPI RSA method"); os_free(priv); os_free(rsa_meth); return -1; } priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER); if (priv->cert == NULL) { priv->cert = cryptoapi_find_cert( name, CERT_SYSTEM_STORE_LOCAL_MACHINE); } if (priv->cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate " "'%s'", name); goto err; } cert = d2i_X509(NULL, (const unsigned char **) &priv->cert->pbCertEncoded, priv->cert->cbCertEncoded); if (cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER " "encoding"); goto err; } if (!CryptAcquireCertificatePrivateKey(priv->cert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &priv->crypt_prov, &priv->key_spec, &priv->free_crypt_prov)) { cryptoapi_error("Failed to acquire a private key for the " "certificate"); goto err; } rsa_meth->name = "Microsoft CryptoAPI RSA Method"; rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc; rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec; rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc; rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec; rsa_meth->finish = cryptoapi_finish; rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; rsa_meth->app_data = (char *) priv; rsa = RSA_new(); if (rsa == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; } if (!SSL_use_certificate(ssl, cert)) { RSA_free(rsa); rsa = NULL; goto err; } pub_rsa = cert->cert_info->key->pkey->pkey.rsa; X509_free(cert); cert = NULL; rsa->n = BN_dup(pub_rsa->n); rsa->e = BN_dup(pub_rsa->e); if (!RSA_set_method(rsa, rsa_meth)) goto err; if (!SSL_use_RSAPrivateKey(ssl, rsa)) goto err; RSA_free(rsa); return 0; err: if (cert) X509_free(cert); if (rsa) RSA_free(rsa); else { os_free(rsa_meth); cryptoapi_free_data(priv); } return -1; } static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name) { HCERTSTORE cs; PCCERT_CONTEXT ctx = NULL; X509 *cert; char buf[128]; const char *store; #ifdef UNICODE WCHAR *wstore; #endif /* UNICODE */ if (name == NULL || strncmp(name, "cert_store://", 13) != 0) return -1; store = name + 13; #ifdef UNICODE wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR)); if (wstore == NULL) return -1; wsprintf(wstore, L"%S", store); cs = CertOpenSystemStore(0, wstore); os_free(wstore); #else /* UNICODE */ cs = CertOpenSystemStore(0, store); #endif /* UNICODE */ if (cs == NULL) { wpa_printf(MSG_DEBUG, "%s: failed to open system cert store " "'%s': error=%d", __func__, store, (int) GetLastError()); return -1; } while ((ctx = CertEnumCertificatesInStore(cs, ctx))) { cert = d2i_X509(NULL, (const unsigned char **) &ctx->pbCertEncoded, ctx->cbCertEncoded); if (cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not process " "X509 DER encoding for CA cert"); continue; } X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for " "system certificate store: subject='%s'", buf); if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx), cert)) { tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert to OpenSSL " "certificate store"); } X509_free(cert); } if (!CertCloseStore(cs, 0)) { wpa_printf(MSG_DEBUG, "%s: failed to close system cert store " "'%s': error=%d", __func__, name + 13, (int) GetLastError()); } return 0; } #else /* CONFIG_NATIVE_WINDOWS */ static int tls_cryptoapi_cert(SSL *ssl, const char *name) { return -1; } #endif /* CONFIG_NATIVE_WINDOWS */ static void ssl_info_cb(const SSL *ssl, int where, int ret) { const char *str; int w; wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret); w = where & ~SSL_ST_MASK; if (w & SSL_ST_CONNECT) str = "SSL_connect"; else if (w & SSL_ST_ACCEPT) str = "SSL_accept"; else str = "undefined"; if (where & SSL_CB_LOOP) { wpa_printf(MSG_DEBUG, "SSL: %s:%s", str, SSL_state_string_long(ssl)); } else if (where & SSL_CB_ALERT) { struct tls_connection *conn = SSL_get_app_data((SSL *) ssl); wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s", where & SSL_CB_READ ? "read (remote end reported an error)" : "write (local SSL3 detected an error)", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); if ((ret >> 8) == SSL3_AL_FATAL) { if (where & SSL_CB_READ) conn->read_alerts++; else conn->write_alerts++; } if (conn->context->event_cb != NULL) { union tls_event_data ev; struct tls_context *context = conn->context; os_memset(&ev, 0, sizeof(ev)); ev.alert.is_local = !(where & SSL_CB_READ); ev.alert.type = SSL_alert_type_string_long(ret); ev.alert.description = SSL_alert_desc_string_long(ret); context->event_cb(context->cb_ctx, TLS_ALERT, &ev); } } else if (where & SSL_CB_EXIT && ret <= 0) { wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s", str, ret == 0 ? "failed" : "error", SSL_state_string_long(ssl)); } } #ifndef OPENSSL_NO_ENGINE /** * tls_engine_load_dynamic_generic - load any openssl engine * @pre: an array of commands and values that load an engine initialized * in the engine specific function * @post: an array of commands and values that initialize an already loaded * engine (or %NULL if not required) * @id: the engine id of the engine to load (only required if post is not %NULL * * This function is a generic function that loads any openssl engine. * * Returns: 0 on success, -1 on failure */ static int tls_engine_load_dynamic_generic(const char *pre[], const char *post[], const char *id) { ENGINE *engine; const char *dynamic_id = "dynamic"; engine = ENGINE_by_id(id); if (engine) { wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already " "available", id); /* * If it was auto-loaded by ENGINE_by_id() we might still * need to tell it which PKCS#11 module to use in legacy * (non-p11-kit) environments. Do so now; even if it was * properly initialised before, setting it again will be * harmless. */ goto found; } ERR_clear_error(); engine = ENGINE_by_id(dynamic_id); if (engine == NULL) { wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", dynamic_id, ERR_error_string(ERR_get_error(), NULL)); return -1; } /* Perform the pre commands. This will load the engine. */ while (pre && pre[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]); if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) { wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: " "%s %s [%s]", pre[0], pre[1], ERR_error_string(ERR_get_error(), NULL)); ENGINE_free(engine); return -1; } pre += 2; } /* * Free the reference to the "dynamic" engine. The loaded engine can * now be looked up using ENGINE_by_id(). */ ENGINE_free(engine); engine = ENGINE_by_id(id); if (engine == NULL) { wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", id, ERR_error_string(ERR_get_error(), NULL)); return -1; } found: while (post && post[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]); if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) { wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:" " %s %s [%s]", post[0], post[1], ERR_error_string(ERR_get_error(), NULL)); ENGINE_remove(engine); ENGINE_free(engine); return -1; } post += 2; } ENGINE_free(engine); return 0; } /** * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc * @pkcs11_so_path: pksc11_so_path from the configuration * @pcks11_module_path: pkcs11_module_path from the configuration */ static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path, const char *pkcs11_module_path) { char *engine_id = "pkcs11"; const char *pre_cmd[] = { "SO_PATH", NULL /* pkcs11_so_path */, "ID", NULL /* engine_id */, "LIST_ADD", "1", /* "NO_VCHECK", "1", */ "LOAD", NULL, NULL, NULL }; const char *post_cmd[] = { "MODULE_PATH", NULL /* pkcs11_module_path */, NULL, NULL }; if (!pkcs11_so_path) return 0; pre_cmd[1] = pkcs11_so_path; pre_cmd[3] = engine_id; if (pkcs11_module_path) post_cmd[1] = pkcs11_module_path; else post_cmd[0] = NULL; wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s", pkcs11_so_path); return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id); } /** * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc * @opensc_so_path: opensc_so_path from the configuration */ static int tls_engine_load_dynamic_opensc(const char *opensc_so_path) { char *engine_id = "opensc"; const char *pre_cmd[] = { "SO_PATH", NULL /* opensc_so_path */, "ID", NULL /* engine_id */, "LIST_ADD", "1", "LOAD", NULL, NULL, NULL }; if (!opensc_so_path) return 0; pre_cmd[1] = opensc_so_path; pre_cmd[3] = engine_id; wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s", opensc_so_path); return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id); } #endif /* OPENSSL_NO_ENGINE */ static void remove_session_cb(SSL_CTX *ctx, SSL_SESSION *sess) { struct wpabuf *buf; if (tls_ex_idx_session < 0) return; buf = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session); if (!buf) return; wpa_printf(MSG_DEBUG, "OpenSSL: Free application session data %p (sess %p)", buf, sess); wpabuf_free(buf); SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, NULL); } void * tls_init(const struct tls_config *conf) { struct tls_data *data; SSL_CTX *ssl; struct tls_context *context; const char *ciphers; if (tls_openssl_ref_count == 0) { + void openssl_load_legacy_provider(void); + + openssl_load_legacy_provider(); + tls_global = context = tls_context_new(conf); if (context == NULL) return NULL; #ifdef CONFIG_FIPS #ifdef OPENSSL_FIPS if (conf && conf->fips_mode) { static int fips_enabled = 0; if (!fips_enabled && !FIPS_mode_set(1)) { wpa_printf(MSG_ERROR, "Failed to enable FIPS " "mode"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); os_free(tls_global); tls_global = NULL; return NULL; } else { wpa_printf(MSG_INFO, "Running in FIPS mode"); fips_enabled = 1; } } #else /* OPENSSL_FIPS */ if (conf && conf->fips_mode) { wpa_printf(MSG_ERROR, "FIPS mode requested, but not " "supported"); os_free(tls_global); tls_global = NULL; return NULL; } #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) SSL_load_error_strings(); SSL_library_init(); #ifndef OPENSSL_NO_SHA256 EVP_add_digest(EVP_sha256()); #endif /* OPENSSL_NO_SHA256 */ /* TODO: if /dev/urandom is available, PRNG is seeded * automatically. If this is not the case, random data should * be added here. */ #ifdef PKCS12_FUNCS #ifndef OPENSSL_NO_RC2 /* * 40-bit RC2 is commonly used in PKCS#12 files, so enable it. * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8 * versions, but it looks like OpenSSL 1.0.0 does not do that * anymore. */ EVP_add_cipher(EVP_rc2_40_cbc()); #endif /* OPENSSL_NO_RC2 */ PKCS12_PBE_add(); #endif /* PKCS12_FUNCS */ #endif /* < 1.1.0 */ } else { context = tls_context_new(conf); if (context == NULL) return NULL; } tls_openssl_ref_count++; data = os_zalloc(sizeof(*data)); if (data) ssl = SSL_CTX_new(SSLv23_method()); else ssl = NULL; if (ssl == NULL) { tls_openssl_ref_count--; if (context != tls_global) os_free(context); if (tls_openssl_ref_count == 0) { os_free(tls_global); tls_global = NULL; } os_free(data); return NULL; } data->ssl = ssl; if (conf) { data->tls_session_lifetime = conf->tls_session_lifetime; data->crl_reload_interval = conf->crl_reload_interval; } SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv2); SSL_CTX_set_options(ssl, SSL_OP_NO_SSLv3); SSL_CTX_set_mode(ssl, SSL_MODE_AUTO_RETRY); #ifdef SSL_MODE_NO_AUTO_CHAIN /* Number of deployed use cases assume the default OpenSSL behavior of * auto chaining the local certificate is in use. BoringSSL removed this * functionality by default, so we need to restore it here to avoid * breaking existing use cases. */ SSL_CTX_clear_mode(ssl, SSL_MODE_NO_AUTO_CHAIN); #endif /* SSL_MODE_NO_AUTO_CHAIN */ SSL_CTX_set_info_callback(ssl, ssl_info_cb); SSL_CTX_set_app_data(ssl, context); if (data->tls_session_lifetime > 0) { SSL_CTX_set_quiet_shutdown(ssl, 1); /* * Set default context here. In practice, this will be replaced * by the per-EAP method context in tls_connection_set_verify(). */ SSL_CTX_set_session_id_context(ssl, (u8 *) "hostapd", 7); SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_SERVER); SSL_CTX_set_timeout(ssl, data->tls_session_lifetime); SSL_CTX_sess_set_remove_cb(ssl, remove_session_cb); } else { SSL_CTX_set_session_cache_mode(ssl, SSL_SESS_CACHE_OFF); } if (tls_ex_idx_session < 0) { tls_ex_idx_session = SSL_SESSION_get_ex_new_index( 0, NULL, NULL, NULL, NULL); if (tls_ex_idx_session < 0) { tls_deinit(data); return NULL; } } #ifndef OPENSSL_NO_ENGINE wpa_printf(MSG_DEBUG, "ENGINE: Loading builtin engines"); ENGINE_load_builtin_engines(); if (conf && (conf->opensc_engine_path || conf->pkcs11_engine_path || conf->pkcs11_module_path)) { if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) || tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path, conf->pkcs11_module_path)) { tls_deinit(data); return NULL; } } #endif /* OPENSSL_NO_ENGINE */ if (conf && conf->openssl_ciphers) ciphers = conf->openssl_ciphers; else ciphers = TLS_DEFAULT_CIPHERS; if (SSL_CTX_set_cipher_list(ssl, ciphers) != 1) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to set cipher string '%s'", ciphers); tls_deinit(data); return NULL; } return data; } void tls_deinit(void *ssl_ctx) { struct tls_data *data = ssl_ctx; SSL_CTX *ssl = data->ssl; struct tls_context *context = SSL_CTX_get_app_data(ssl); if (context != tls_global) os_free(context); if (data->tls_session_lifetime > 0) SSL_CTX_flush_sessions(ssl, 0); os_free(data->ca_cert); SSL_CTX_free(ssl); tls_openssl_ref_count--; if (tls_openssl_ref_count == 0) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif /* OPENSSL_NO_ENGINE */ CRYPTO_cleanup_all_ex_data(); ERR_remove_thread_state(NULL); ERR_free_strings(); EVP_cleanup(); #endif /* < 1.1.0 */ os_free(tls_global->ocsp_stapling_response); tls_global->ocsp_stapling_response = NULL; os_free(tls_global); tls_global = NULL; } os_free(data->check_cert_subject); os_free(data); } #ifndef OPENSSL_NO_ENGINE /* Cryptoki return values */ #define CKR_PIN_INCORRECT 0x000000a0 #define CKR_PIN_INVALID 0x000000a1 #define CKR_PIN_LEN_RANGE 0x000000a2 /* libp11 */ #define ERR_LIB_PKCS11 ERR_LIB_USER static int tls_is_pin_error(unsigned int err) { return ERR_GET_LIB(err) == ERR_LIB_PKCS11 && (ERR_GET_REASON(err) == CKR_PIN_INCORRECT || ERR_GET_REASON(err) == CKR_PIN_INVALID || ERR_GET_REASON(err) == CKR_PIN_LEN_RANGE); } #endif /* OPENSSL_NO_ENGINE */ #ifdef ANDROID /* EVP_PKEY_from_keystore comes from system/security/keystore-engine. */ EVP_PKEY * EVP_PKEY_from_keystore(const char *key_id); #endif /* ANDROID */ static int tls_engine_init(struct tls_connection *conn, const char *engine_id, const char *pin, const char *key_id, const char *cert_id, const char *ca_cert_id) { #if defined(ANDROID) && defined(OPENSSL_IS_BORINGSSL) #if !defined(OPENSSL_NO_ENGINE) #error "This code depends on OPENSSL_NO_ENGINE being defined by BoringSSL." #endif if (!key_id) return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; conn->engine = NULL; conn->private_key = EVP_PKEY_from_keystore(key_id); if (!conn->private_key) { wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id '%s' [%s]", key_id, ERR_error_string(ERR_get_error(), NULL)); return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } #endif /* ANDROID && OPENSSL_IS_BORINGSSL */ #ifndef OPENSSL_NO_ENGINE int ret = -1; if (engine_id == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set"); return -1; } ERR_clear_error(); #ifdef ANDROID ENGINE_load_dynamic(); #endif conn->engine = ENGINE_by_id(engine_id); if (!conn->engine) { wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]", engine_id, ERR_error_string(ERR_get_error(), NULL)); goto err; } if (ENGINE_init(conn->engine) != 1) { wpa_printf(MSG_ERROR, "ENGINE: engine init failed " "(engine: %s) [%s]", engine_id, ERR_error_string(ERR_get_error(), NULL)); goto err; } wpa_printf(MSG_DEBUG, "ENGINE: engine initialized"); #ifndef ANDROID if (pin && ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) { wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]", ERR_error_string(ERR_get_error(), NULL)); goto err; } #endif if (key_id) { /* * Ensure that the ENGINE does not attempt to use the OpenSSL * UI system to obtain a PIN, if we didn't provide one. */ struct { const void *password; const char *prompt_info; } key_cb = { "", NULL }; /* load private key first in-case PIN is required for cert */ conn->private_key = ENGINE_load_private_key(conn->engine, key_id, NULL, &key_cb); if (!conn->private_key) { unsigned long err = ERR_get_error(); wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id '%s' [%s]", key_id, ERR_error_string(err, NULL)); if (tls_is_pin_error(err)) ret = TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN; else ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; goto err; } } /* handle a certificate and/or CA certificate */ if (cert_id || ca_cert_id) { const char *cmd_name = "LOAD_CERT_CTRL"; /* test if the engine supports a LOAD_CERT_CTRL */ if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME, 0, (void *)cmd_name, NULL)) { wpa_printf(MSG_ERROR, "ENGINE: engine does not support" " loading certificates"); ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; goto err; } } return 0; err: if (conn->engine) { ENGINE_free(conn->engine); conn->engine = NULL; } if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } return ret; #else /* OPENSSL_NO_ENGINE */ return 0; #endif /* OPENSSL_NO_ENGINE */ } static void tls_engine_deinit(struct tls_connection *conn) { #if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE) wpa_printf(MSG_DEBUG, "ENGINE: engine deinit"); if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } if (conn->engine) { #if !defined(OPENSSL_IS_BORINGSSL) ENGINE_finish(conn->engine); #endif /* !OPENSSL_IS_BORINGSSL */ conn->engine = NULL; } #endif /* ANDROID || !OPENSSL_NO_ENGINE */ } int tls_get_errors(void *ssl_ctx) { int count = 0; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "TLS - SSL error: %s", ERR_error_string(err, NULL)); count++; } return count; } static const char * openssl_content_type(int content_type) { switch (content_type) { case 20: return "change cipher spec"; case 21: return "alert"; case 22: return "handshake"; case 23: return "application data"; case 24: return "heartbeat"; case 256: return "TLS header info"; /* pseudo content type */ case 257: return "inner content type"; /* pseudo content type */ default: return "?"; } } static const char * openssl_handshake_type(int content_type, const u8 *buf, size_t len) { if (content_type == 257 && buf && len == 1) return openssl_content_type(buf[0]); if (content_type != 22 || !buf || len == 0) return ""; switch (buf[0]) { case 0: return "hello request"; case 1: return "client hello"; case 2: return "server hello"; case 3: return "hello verify request"; case 4: return "new session ticket"; case 5: return "end of early data"; case 6: return "hello retry request"; case 8: return "encrypted extensions"; case 11: return "certificate"; case 12: return "server key exchange"; case 13: return "certificate request"; case 14: return "server hello done"; case 15: return "certificate verify"; case 16: return "client key exchange"; case 20: return "finished"; case 21: return "certificate url"; case 22: return "certificate status"; case 23: return "supplemental data"; case 24: return "key update"; case 254: return "message hash"; default: return "?"; } } #ifdef CONFIG_SUITEB static void check_server_hello(struct tls_connection *conn, const u8 *pos, const u8 *end) { size_t payload_len, id_len; /* * Parse ServerHello to get the selected cipher suite since OpenSSL does * not make it cleanly available during handshake and we need to know * whether DHE was selected. */ if (end - pos < 3) return; payload_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < payload_len) return; end = pos + payload_len; /* Skip Version and Random */ if (end - pos < 2 + SSL3_RANDOM_SIZE) return; pos += 2 + SSL3_RANDOM_SIZE; /* Skip Session ID */ if (end - pos < 1) return; id_len = *pos++; if ((size_t) (end - pos) < id_len) return; pos += id_len; if (end - pos < 2) return; conn->cipher_suite = WPA_GET_BE16(pos); wpa_printf(MSG_DEBUG, "OpenSSL: Server selected cipher suite 0x%x", conn->cipher_suite); } static void check_server_key_exchange(SSL *ssl, struct tls_connection *conn, const u8 *pos, const u8 *end) { size_t payload_len; u16 dh_len; BIGNUM *p; int bits; if (!(conn->flags & TLS_CONN_SUITEB)) return; /* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */ if (conn->cipher_suite != 0x9f) return; if (end - pos < 3) return; payload_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < payload_len) return; end = pos + payload_len; if (end - pos < 2) return; dh_len = WPA_GET_BE16(pos); pos += 2; if ((size_t) (end - pos) < dh_len) return; p = BN_bin2bn(pos, dh_len, NULL); if (!p) return; bits = BN_num_bits(p); BN_free(p); conn->server_dh_prime_len = bits; wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length: %d bits", conn->server_dh_prime_len); } #endif /* CONFIG_SUITEB */ static void tls_msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg) { struct tls_connection *conn = arg; const u8 *pos = buf; if (write_p == 2) { wpa_printf(MSG_DEBUG, "OpenSSL: session ver=0x%x content_type=%d", version, content_type); wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Data", buf, len); return; } wpa_printf(MSG_DEBUG, "OpenSSL: %s ver=0x%x content_type=%d (%s/%s)", write_p ? "TX" : "RX", version, content_type, openssl_content_type(content_type), openssl_handshake_type(content_type, buf, len)); wpa_hexdump_key(MSG_MSGDUMP, "OpenSSL: Message", buf, len); if (content_type == 24 && len >= 3 && pos[0] == 1) { size_t payload_len = WPA_GET_BE16(pos + 1); if (payload_len + 3 > len) { wpa_printf(MSG_ERROR, "OpenSSL: Heartbeat attack detected"); conn->invalid_hb_used = 1; } } #ifdef CONFIG_SUITEB /* * Need to parse these handshake messages to be able to check DH prime * length since OpenSSL does not expose the new cipher suite and DH * parameters during handshake (e.g., for cert_cb() callback). */ if (content_type == 22 && pos && len > 0 && pos[0] == 2) check_server_hello(conn, pos + 1, pos + len); if (content_type == 22 && pos && len > 0 && pos[0] == 12) check_server_key_exchange(ssl, conn, pos + 1, pos + len); #endif /* CONFIG_SUITEB */ } struct tls_connection * tls_connection_init(void *ssl_ctx) { struct tls_data *data = ssl_ctx; SSL_CTX *ssl = data->ssl; struct tls_connection *conn; long options; X509_STORE *new_cert_store; struct os_reltime now; struct tls_context *context = SSL_CTX_get_app_data(ssl); /* Replace X509 store if it is time to update CRL. */ if (data->crl_reload_interval > 0 && os_get_reltime(&now) == 0 && os_reltime_expired(&now, &data->crl_last_reload, data->crl_reload_interval)) { wpa_printf(MSG_INFO, "OpenSSL: Flushing X509 store with ca_cert file"); new_cert_store = tls_crl_cert_reload(data->ca_cert, data->check_crl); if (!new_cert_store) { wpa_printf(MSG_ERROR, "OpenSSL: Error replacing X509 store with ca_cert file"); } else { /* Replace old store */ SSL_CTX_set_cert_store(ssl, new_cert_store); data->crl_last_reload = now; } } conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->data = data; conn->ssl_ctx = ssl; conn->ssl = SSL_new(ssl); if (conn->ssl == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to initialize new SSL connection"); os_free(conn); return NULL; } conn->context = context; SSL_set_app_data(conn->ssl, conn); SSL_set_msg_callback(conn->ssl, tls_msg_cb); SSL_set_msg_callback_arg(conn->ssl, conn); options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE; #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /* SSL_OP_NO_COMPRESSION */ SSL_set_options(conn->ssl, options); #ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* Hopefully there is no need for middlebox compatibility mechanisms * when going through EAP authentication. */ SSL_clear_options(conn->ssl, SSL_OP_ENABLE_MIDDLEBOX_COMPAT); #endif conn->ssl_in = BIO_new(BIO_s_mem()); if (!conn->ssl_in) { tls_show_errors(MSG_INFO, __func__, "Failed to create a new BIO for ssl_in"); SSL_free(conn->ssl); os_free(conn); return NULL; } conn->ssl_out = BIO_new(BIO_s_mem()); if (!conn->ssl_out) { tls_show_errors(MSG_INFO, __func__, "Failed to create a new BIO for ssl_out"); SSL_free(conn->ssl); BIO_free(conn->ssl_in); os_free(conn); return NULL; } SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out); return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; if (conn->success_data) { /* * Make sure ssl_clear_bad_session() does not remove this * session. */ SSL_set_quiet_shutdown(conn->ssl, 1); SSL_shutdown(conn->ssl); } SSL_free(conn->ssl); tls_engine_deinit(conn); os_free(conn->subject_match); os_free(conn->altsubject_match); os_free(conn->suffix_match); os_free(conn->domain_match); os_free(conn->check_cert_subject); os_free(conn->session_ticket); os_free(conn->peer_subject); os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? SSL_is_init_finished(conn->ssl) : 0; } char * tls_connection_peer_serial_num(void *tls_ctx, struct tls_connection *conn) { ASN1_INTEGER *ser; char *serial_num; size_t len; if (!conn->peer_cert) return NULL; ser = X509_get_serialNumber(conn->peer_cert); if (!ser) return NULL; len = ASN1_STRING_length(ser) * 2 + 1; serial_num = os_malloc(len); if (!serial_num) return NULL; wpa_snprintf_hex_uppercase(serial_num, len, ASN1_STRING_get0_data(ser), ASN1_STRING_length(ser)); return serial_num; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; /* Shutdown previous TLS connection without notifying the peer * because the connection was already terminated in practice * and "close notify" shutdown alert would confuse AS. */ SSL_set_quiet_shutdown(conn->ssl, 1); SSL_shutdown(conn->ssl); return SSL_clear(conn->ssl) == 1 ? 0 : -1; } static int tls_match_altsubject_component(X509 *cert, int type, const char *value, size_t len) { GENERAL_NAME *gen; void *ext; int found = 0; stack_index_t i; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { gen = sk_GENERAL_NAME_value(ext, i); if (gen->type != type) continue; if (os_strlen((char *) gen->d.ia5->data) == len && os_memcmp(value, gen->d.ia5->data, len) == 0) found++; } sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); return found; } static int tls_match_altsubject(X509 *cert, const char *match) { int type; const char *pos, *end; size_t len; pos = match; do { if (os_strncmp(pos, "EMAIL:", 6) == 0) { type = GEN_EMAIL; pos += 6; } else if (os_strncmp(pos, "DNS:", 4) == 0) { type = GEN_DNS; pos += 4; } else if (os_strncmp(pos, "URI:", 4) == 0) { type = GEN_URI; pos += 4; } else { wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName " "match '%s'", pos); return 0; } end = os_strchr(pos, ';'); while (end) { if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || os_strncmp(end + 1, "DNS:", 4) == 0 || os_strncmp(end + 1, "URI:", 4) == 0) break; end = os_strchr(end + 1, ';'); } if (end) len = end - pos; else len = os_strlen(pos); if (tls_match_altsubject_component(cert, type, pos, len) > 0) return 1; pos = end + 1; } while (end); return 0; } #ifndef CONFIG_NATIVE_WINDOWS static int domain_suffix_match(const u8 *val, size_t len, const char *match, size_t match_len, int full) { size_t i; /* Check for embedded nuls that could mess up suffix matching */ for (i = 0; i < len; i++) { if (val[i] == '\0') { wpa_printf(MSG_DEBUG, "TLS: Embedded null in a string - reject"); return 0; } } if (match_len > len || (full && match_len != len)) return 0; if (os_strncasecmp((const char *) val + len - match_len, match, match_len) != 0) return 0; /* no match */ if (match_len == len) return 1; /* exact match */ if (val[len - match_len - 1] == '.') return 1; /* full label match completes suffix match */ wpa_printf(MSG_DEBUG, "TLS: Reject due to incomplete label match"); return 0; } #endif /* CONFIG_NATIVE_WINDOWS */ struct tls_dn_field_order_cnt { u8 cn; u8 c; u8 l; u8 st; u8 o; u8 ou; u8 email; }; static int get_dn_field_index(const struct tls_dn_field_order_cnt *dn_cnt, int nid) { switch (nid) { case NID_commonName: return dn_cnt->cn; case NID_countryName: return dn_cnt->c; case NID_localityName: return dn_cnt->l; case NID_stateOrProvinceName: return dn_cnt->st; case NID_organizationName: return dn_cnt->o; case NID_organizationalUnitName: return dn_cnt->ou; case NID_pkcs9_emailAddress: return dn_cnt->email; default: wpa_printf(MSG_ERROR, "TLS: Unknown NID '%d' in check_cert_subject", nid); return -1; } } /** * match_dn_field - Match configuration DN field against Certificate DN field * @cert: Certificate * @nid: NID of DN field * @field: Field name * @value DN field value which is passed from configuration * e.g., if configuration have C=US and this argument will point to US. * @dn_cnt: DN matching context * Returns: 1 on success and 0 on failure */ static int match_dn_field(const X509 *cert, int nid, const char *field, const char *value, const struct tls_dn_field_order_cnt *dn_cnt) { int i, ret = 0, len, config_dn_field_index, match_index = 0; X509_NAME *name; len = os_strlen(value); name = X509_get_subject_name((X509 *) cert); /* Assign incremented cnt for every field of DN to check DN field in * right order */ config_dn_field_index = get_dn_field_index(dn_cnt, nid); if (config_dn_field_index < 0) return 0; /* Fetch value based on NID */ for (i = -1; (i = X509_NAME_get_index_by_NID(name, nid, i)) > -1;) { X509_NAME_ENTRY *e; ASN1_STRING *cn; e = X509_NAME_get_entry(name, i); if (!e) continue; cn = X509_NAME_ENTRY_get_data(e); if (!cn) continue; match_index++; /* check for more than one DN field with same name */ if (match_index != config_dn_field_index) continue; /* Check wildcard at the right end side */ /* E.g., if OU=develop* mentioned in configuration, allow 'OU' * of the subject in the client certificate to start with * 'develop' */ if (len > 0 && value[len - 1] == '*') { /* Compare actual certificate DN field value with * configuration DN field value up to the specified * length. */ ret = ASN1_STRING_length(cn) >= len - 1 && os_memcmp(ASN1_STRING_get0_data(cn), value, len - 1) == 0; } else { /* Compare actual certificate DN field value with * configuration DN field value */ ret = ASN1_STRING_length(cn) == len && os_memcmp(ASN1_STRING_get0_data(cn), value, len) == 0; } if (!ret) { wpa_printf(MSG_ERROR, "OpenSSL: Failed to match %s '%s' with certificate DN field value '%s'", field, value, ASN1_STRING_get0_data(cn)); } break; } return ret; } /** * get_value_from_field - Get value from DN field * @cert: Certificate * @field_str: DN field string which is passed from configuration file (e.g., * C=US) * @dn_cnt: DN matching context * Returns: 1 on success and 0 on failure */ static int get_value_from_field(const X509 *cert, char *field_str, struct tls_dn_field_order_cnt *dn_cnt) { int nid; char *context = NULL, *name, *value; if (os_strcmp(field_str, "*") == 0) return 1; /* wildcard matches everything */ name = str_token(field_str, "=", &context); if (!name) return 0; /* Compare all configured DN fields and assign nid based on that to * fetch correct value from certificate subject */ if (os_strcmp(name, "CN") == 0) { nid = NID_commonName; dn_cnt->cn++; } else if(os_strcmp(name, "C") == 0) { nid = NID_countryName; dn_cnt->c++; } else if (os_strcmp(name, "L") == 0) { nid = NID_localityName; dn_cnt->l++; } else if (os_strcmp(name, "ST") == 0) { nid = NID_stateOrProvinceName; dn_cnt->st++; } else if (os_strcmp(name, "O") == 0) { nid = NID_organizationName; dn_cnt->o++; } else if (os_strcmp(name, "OU") == 0) { nid = NID_organizationalUnitName; dn_cnt->ou++; } else if (os_strcmp(name, "emailAddress") == 0) { nid = NID_pkcs9_emailAddress; dn_cnt->email++; } else { wpa_printf(MSG_ERROR, "TLS: Unknown field '%s' in check_cert_subject", name); return 0; } value = str_token(field_str, "=", &context); if (!value) { wpa_printf(MSG_ERROR, "TLS: Distinguished Name field '%s' value is not defined in check_cert_subject", name); return 0; } return match_dn_field(cert, nid, name, value, dn_cnt); } /** * tls_match_dn_field - Match subject DN field with check_cert_subject * @cert: Certificate * @match: check_cert_subject string * Returns: Return 1 on success and 0 on failure */ static int tls_match_dn_field(X509 *cert, const char *match) { const char *token, *last = NULL; char field[256]; struct tls_dn_field_order_cnt dn_cnt; os_memset(&dn_cnt, 0, sizeof(dn_cnt)); /* Maximum length of each DN field is 255 characters */ /* Process each '/' delimited field */ while ((token = cstr_token(match, "/", &last))) { if (last - token >= (int) sizeof(field)) { wpa_printf(MSG_ERROR, "OpenSSL: Too long DN matching field value in '%s'", match); return 0; } os_memcpy(field, token, last - token); field[last - token] = '\0'; if (!get_value_from_field(cert, field, &dn_cnt)) { wpa_printf(MSG_DEBUG, "OpenSSL: No match for DN '%s'", field); return 0; } } return 1; } #ifndef CONFIG_NATIVE_WINDOWS static int tls_match_suffix_helper(X509 *cert, const char *match, size_t match_len, int full) { GENERAL_NAME *gen; void *ext; int i; stack_index_t j; int dns_name = 0; X509_NAME *name; wpa_printf(MSG_DEBUG, "TLS: Match domain against %s%s", full ? "": "suffix ", match); ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (j = 0; ext && j < sk_GENERAL_NAME_num(ext); j++) { gen = sk_GENERAL_NAME_value(ext, j); if (gen->type != GEN_DNS) continue; dns_name++; wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName", gen->d.dNSName->data, gen->d.dNSName->length); if (domain_suffix_match(gen->d.dNSName->data, gen->d.dNSName->length, match, match_len, full) == 1) { wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found", full ? "Match" : "Suffix match"); sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); return 1; } } sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); if (dns_name) { wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched"); return 0; } name = X509_get_subject_name(cert); i = -1; for (;;) { X509_NAME_ENTRY *e; ASN1_STRING *cn; i = X509_NAME_get_index_by_NID(name, NID_commonName, i); if (i == -1) break; e = X509_NAME_get_entry(name, i); if (e == NULL) continue; cn = X509_NAME_ENTRY_get_data(e); if (cn == NULL) continue; wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate commonName", cn->data, cn->length); if (domain_suffix_match(cn->data, cn->length, match, match_len, full) == 1) { wpa_printf(MSG_DEBUG, "TLS: %s in commonName found", full ? "Match" : "Suffix match"); return 1; } } wpa_printf(MSG_DEBUG, "TLS: No CommonName %smatch found", full ? "": "suffix "); return 0; } #endif /* CONFIG_NATIVE_WINDOWS */ static int tls_match_suffix(X509 *cert, const char *match, int full) { #ifdef CONFIG_NATIVE_WINDOWS /* wincrypt.h has conflicting X509_NAME definition */ return -1; #else /* CONFIG_NATIVE_WINDOWS */ const char *token, *last = NULL; /* Process each match alternative separately until a match is found */ while ((token = cstr_token(match, ";", &last))) { if (tls_match_suffix_helper(cert, token, last - token, full)) return 1; } return 0; #endif /* CONFIG_NATIVE_WINDOWS */ } static enum tls_fail_reason openssl_tls_fail_reason(int err) { switch (err) { case X509_V_ERR_CERT_REVOKED: return TLS_FAIL_REVOKED; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: return TLS_FAIL_NOT_YET_VALID; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_HAS_EXPIRED: return TLS_FAIL_EXPIRED; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_GET_CRL: case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_CERT_CHAIN_TOO_LONG: case X509_V_ERR_PATH_LENGTH_EXCEEDED: case X509_V_ERR_INVALID_CA: return TLS_FAIL_UNTRUSTED; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_CERT_REJECTED: return TLS_FAIL_BAD_CERTIFICATE; default: return TLS_FAIL_UNSPECIFIED; } } static struct wpabuf * get_x509_cert(X509 *cert) { struct wpabuf *buf; u8 *tmp; int cert_len = i2d_X509(cert, NULL); if (cert_len <= 0) return NULL; buf = wpabuf_alloc(cert_len); if (buf == NULL) return NULL; tmp = wpabuf_put(buf, cert_len); i2d_X509(cert, &tmp); return buf; } static void openssl_tls_fail_event(struct tls_connection *conn, X509 *err_cert, int err, int depth, const char *subject, const char *err_str, enum tls_fail_reason reason) { union tls_event_data ev; struct wpabuf *cert = NULL; struct tls_context *context = conn->context; if (context->event_cb == NULL) return; cert = get_x509_cert(err_cert); os_memset(&ev, 0, sizeof(ev)); ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ? reason : openssl_tls_fail_reason(err); ev.cert_fail.depth = depth; ev.cert_fail.subject = subject; ev.cert_fail.reason_txt = err_str; ev.cert_fail.cert = cert; context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); wpabuf_free(cert); } static int openssl_cert_tod(X509 *cert) { CERTIFICATEPOLICIES *ext; stack_index_t i; char buf[100]; int res; int tod = 0; ext = X509_get_ext_d2i(cert, NID_certificate_policies, NULL, NULL); if (!ext) return 0; for (i = 0; i < sk_POLICYINFO_num(ext); i++) { POLICYINFO *policy; policy = sk_POLICYINFO_value(ext, i); res = OBJ_obj2txt(buf, sizeof(buf), policy->policyid, 0); if (res < 0 || (size_t) res >= sizeof(buf)) continue; wpa_printf(MSG_DEBUG, "OpenSSL: Certificate Policy %s", buf); if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.1") == 0) tod = 1; /* TOD-STRICT */ else if (os_strcmp(buf, "1.3.6.1.4.1.40808.1.3.2") == 0 && !tod) tod = 2; /* TOD-TOFU */ } sk_POLICYINFO_pop_free(ext, POLICYINFO_free); return tod; } static void openssl_tls_cert_event(struct tls_connection *conn, X509 *err_cert, int depth, const char *subject) { struct wpabuf *cert = NULL; union tls_event_data ev; struct tls_context *context = conn->context; char *altsubject[TLS_MAX_ALT_SUBJECT]; int alt, num_altsubject = 0; GENERAL_NAME *gen; void *ext; stack_index_t i; ASN1_INTEGER *ser; char serial_num[128]; #ifdef CONFIG_SHA256 u8 hash[32]; #endif /* CONFIG_SHA256 */ if (context->event_cb == NULL) return; os_memset(&ev, 0, sizeof(ev)); if (conn->cert_probe || (conn->flags & TLS_CONN_EXT_CERT_CHECK) || context->cert_in_cb) { cert = get_x509_cert(err_cert); ev.peer_cert.cert = cert; } #ifdef CONFIG_SHA256 if (cert) { const u8 *addr[1]; size_t len[1]; addr[0] = wpabuf_head(cert); len[0] = wpabuf_len(cert); if (sha256_vector(1, addr, len, hash) == 0) { ev.peer_cert.hash = hash; ev.peer_cert.hash_len = sizeof(hash); } } #endif /* CONFIG_SHA256 */ ev.peer_cert.depth = depth; ev.peer_cert.subject = subject; ser = X509_get_serialNumber(err_cert); if (ser) { wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num), ASN1_STRING_get0_data(ser), ASN1_STRING_length(ser)); ev.peer_cert.serial_num = serial_num; } ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { char *pos; if (num_altsubject == TLS_MAX_ALT_SUBJECT) break; gen = sk_GENERAL_NAME_value(ext, i); if (gen->type != GEN_EMAIL && gen->type != GEN_DNS && gen->type != GEN_URI) continue; pos = os_malloc(10 + gen->d.ia5->length + 1); if (pos == NULL) break; altsubject[num_altsubject++] = pos; switch (gen->type) { case GEN_EMAIL: os_memcpy(pos, "EMAIL:", 6); pos += 6; break; case GEN_DNS: os_memcpy(pos, "DNS:", 4); pos += 4; break; case GEN_URI: os_memcpy(pos, "URI:", 4); pos += 4; break; } os_memcpy(pos, gen->d.ia5->data, gen->d.ia5->length); pos += gen->d.ia5->length; *pos = '\0'; } sk_GENERAL_NAME_pop_free(ext, GENERAL_NAME_free); for (alt = 0; alt < num_altsubject; alt++) ev.peer_cert.altsubject[alt] = altsubject[alt]; ev.peer_cert.num_altsubject = num_altsubject; ev.peer_cert.tod = openssl_cert_tod(err_cert); context->event_cb(context->cb_ctx, TLS_PEER_CERTIFICATE, &ev); wpabuf_free(cert); for (alt = 0; alt < num_altsubject; alt++) os_free(altsubject[alt]); } static void debug_print_cert(X509 *cert, const char *title) { #ifndef CONFIG_NO_STDOUT_DEBUG BIO *out; size_t rlen; char *txt; int res; if (wpa_debug_level > MSG_DEBUG) return; out = BIO_new(BIO_s_mem()); if (!out) return; X509_print(out, cert); rlen = BIO_ctrl_pending(out); txt = os_malloc(rlen + 1); if (txt) { res = BIO_read(out, txt, rlen); if (res > 0) { txt[res] = '\0'; wpa_printf(MSG_DEBUG, "OpenSSL: %s\n%s", title, txt); } os_free(txt); } BIO_free(out); #endif /* CONFIG_NO_STDOUT_DEBUG */ } static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { char buf[256]; X509 *err_cert; int err, depth; SSL *ssl; struct tls_connection *conn; struct tls_context *context; char *match, *altmatch, *suffix_match, *domain_match; const char *check_cert_subject; const char *err_str; err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); if (!err_cert) return 0; err = X509_STORE_CTX_get_error(x509_ctx); depth = X509_STORE_CTX_get_error_depth(x509_ctx); ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); os_snprintf(buf, sizeof(buf), "Peer certificate - depth %d", depth); debug_print_cert(err_cert, buf); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); conn = SSL_get_app_data(ssl); if (conn == NULL) return 0; if (depth == 0) conn->peer_cert = err_cert; else if (depth == 1) conn->peer_issuer = err_cert; else if (depth == 2) conn->peer_issuer_issuer = err_cert; context = conn->context; match = conn->subject_match; altmatch = conn->altsubject_match; suffix_match = conn->suffix_match; domain_match = conn->domain_match; if (!preverify_ok && !conn->ca_cert_verify) preverify_ok = 1; if (!preverify_ok && depth > 0 && conn->server_cert_only) preverify_ok = 1; if (!preverify_ok && (conn->flags & TLS_CONN_DISABLE_TIME_CHECKS) && (err == X509_V_ERR_CERT_HAS_EXPIRED || err == X509_V_ERR_CERT_NOT_YET_VALID)) { wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity " "time mismatch"); preverify_ok = 1; } if (!preverify_ok && !conn->data->check_crl_strict && (err == X509_V_ERR_CRL_HAS_EXPIRED || err == X509_V_ERR_CRL_NOT_YET_VALID)) { wpa_printf(MSG_DEBUG, "OpenSSL: Ignore certificate validity CRL time mismatch"); preverify_ok = 1; } err_str = X509_verify_cert_error_string(err); #ifdef CONFIG_SHA256 /* * Do not require preverify_ok so we can explicity allow otherwise * invalid pinned server certificates. */ if (depth == 0 && conn->server_cert_only) { struct wpabuf *cert; cert = get_x509_cert(err_cert); if (!cert) { wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch " "server certificate data"); preverify_ok = 0; } else { u8 hash[32]; const u8 *addr[1]; size_t len[1]; addr[0] = wpabuf_head(cert); len[0] = wpabuf_len(cert); if (sha256_vector(1, addr, len, hash) < 0 || os_memcmp(conn->srv_cert_hash, hash, 32) != 0) { err_str = "Server certificate mismatch"; err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; preverify_ok = 0; } else if (!preverify_ok) { /* * Certificate matches pinned certificate, allow * regardless of other problems. */ wpa_printf(MSG_DEBUG, "OpenSSL: Ignore validation issues for a pinned server certificate"); preverify_ok = 1; } wpabuf_free(cert); } } #endif /* CONFIG_SHA256 */ openssl_tls_cert_event(conn, err_cert, depth, buf); if (!preverify_ok) { if (depth > 0) { /* Send cert event for the peer certificate so that * the upper layers get information about it even if * validation of a CA certificate fails. */ STACK_OF(X509) *chain; chain = X509_STORE_CTX_get1_chain(x509_ctx); if (chain && sk_X509_num(chain) > 0) { char buf2[256]; X509 *cert; cert = sk_X509_value(chain, 0); X509_NAME_oneline(X509_get_subject_name(cert), buf2, sizeof(buf2)); openssl_tls_cert_event(conn, cert, 0, buf2); } if (chain) sk_X509_pop_free(chain, X509_free); } wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," " error %d (%s) depth %d for '%s'", err, err_str, depth, buf); openssl_tls_fail_event(conn, err_cert, err, depth, buf, err_str, TLS_FAIL_UNSPECIFIED); return preverify_ok; } wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d " "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'", preverify_ok, err, err_str, conn->ca_cert_verify, depth, buf); check_cert_subject = conn->check_cert_subject; if (!check_cert_subject) check_cert_subject = conn->data->check_cert_subject; if (check_cert_subject) { if (depth == 0 && !tls_match_dn_field(err_cert, check_cert_subject)) { preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Distinguished Name", TLS_FAIL_DN_MISMATCH); } } if (depth == 0 && match && os_strstr(buf, match) == NULL) { wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " "match with '%s'", buf, match); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Subject mismatch", TLS_FAIL_SUBJECT_MISMATCH); } else if (depth == 0 && altmatch && !tls_match_altsubject(err_cert, altmatch)) { wpa_printf(MSG_WARNING, "TLS: altSubjectName match " "'%s' not found", altmatch); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "AltSubject mismatch", TLS_FAIL_ALTSUBJECT_MISMATCH); } else if (depth == 0 && suffix_match && !tls_match_suffix(err_cert, suffix_match, 0)) { wpa_printf(MSG_WARNING, "TLS: Domain suffix match '%s' not found", suffix_match); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Domain suffix mismatch", TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); } else if (depth == 0 && domain_match && !tls_match_suffix(err_cert, domain_match, 1)) { wpa_printf(MSG_WARNING, "TLS: Domain match '%s' not found", domain_match); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Domain mismatch", TLS_FAIL_DOMAIN_MISMATCH); } if (conn->cert_probe && preverify_ok && depth == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate " "on probe-only run"); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Server certificate chain probe", TLS_FAIL_SERVER_CHAIN_PROBE); } #ifdef CONFIG_SUITEB if (conn->flags & TLS_CONN_SUITEB) { EVP_PKEY *pk; RSA *rsa; int len = -1; pk = X509_get_pubkey(err_cert); if (pk) { rsa = EVP_PKEY_get1_RSA(pk); if (rsa) { len = RSA_bits(rsa); RSA_free(rsa); } EVP_PKEY_free(pk); } if (len >= 0) { wpa_printf(MSG_DEBUG, "OpenSSL: RSA modulus size: %d bits", len); if (len < 3072) { preverify_ok = 0; openssl_tls_fail_event( conn, err_cert, err, depth, buf, "Insufficient RSA modulus size", TLS_FAIL_INSUFFICIENT_KEY_LEN); } } } #endif /* CONFIG_SUITEB */ #ifdef OPENSSL_IS_BORINGSSL if (depth == 0 && (conn->flags & TLS_CONN_REQUEST_OCSP) && preverify_ok) { enum ocsp_result res; res = check_ocsp_resp(conn->ssl_ctx, conn->ssl, err_cert, conn->peer_issuer, conn->peer_issuer_issuer); if (res == OCSP_REVOKED) { preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "certificate revoked", TLS_FAIL_REVOKED); if (err == X509_V_OK) X509_STORE_CTX_set_error( x509_ctx, X509_V_ERR_CERT_REVOKED); } else if (res != OCSP_GOOD && (conn->flags & TLS_CONN_REQUIRE_OCSP)) { preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "bad certificate status response", TLS_FAIL_UNSPECIFIED); } } #endif /* OPENSSL_IS_BORINGSSL */ if (depth == 0 && preverify_ok && context->event_cb != NULL) context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_SUCCESS, NULL); if (depth == 0 && preverify_ok) { os_free(conn->peer_subject); conn->peer_subject = os_strdup(buf); } return preverify_ok; } #ifndef OPENSSL_NO_STDIO static int tls_load_ca_der(struct tls_data *data, const char *ca_cert) { SSL_CTX *ssl_ctx = data->ssl; X509_LOOKUP *lookup; int ret = 0; lookup = X509_STORE_add_lookup(SSL_CTX_get_cert_store(ssl_ctx), X509_LOOKUP_file()); if (lookup == NULL) { tls_show_errors(MSG_WARNING, __func__, "Failed add lookup for X509 store"); return -1; } if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed load CA in DER format"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " "cert already in hash table error", __func__); } else ret = -1; } return ret; } #endif /* OPENSSL_NO_STDIO */ static int tls_connection_ca_cert(struct tls_data *data, struct tls_connection *conn, const char *ca_cert, const u8 *ca_cert_blob, size_t ca_cert_blob_len, const char *ca_path) { SSL_CTX *ssl_ctx = data->ssl; X509_STORE *store; /* * Remove previously configured trusted CA certificates before adding * new ones. */ store = X509_STORE_new(); if (store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); return -1; } SSL_CTX_set_cert_store(ssl_ctx, store); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); conn->ca_cert_verify = 1; if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate " "chain"); conn->cert_probe = 1; conn->ca_cert_verify = 0; return 0; } if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { #ifdef CONFIG_SHA256 const char *pos = ca_cert + 7; if (os_strncmp(pos, "server/sha256/", 14) != 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert " "hash value '%s'", ca_cert); return -1; } pos += 14; if (os_strlen(pos) != 32 * 2) { wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 " "hash length in ca_cert '%s'", ca_cert); return -1; } if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash " "value in ca_cert '%s'", ca_cert); return -1; } conn->server_cert_only = 1; wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server " "certificate match"); return 0; #else /* CONFIG_SHA256 */ wpa_printf(MSG_INFO, "No SHA256 included in the build - " "cannot validate server certificate hash"); return -1; #endif /* CONFIG_SHA256 */ } if (ca_cert_blob) { X509 *cert = d2i_X509(NULL, (const unsigned char **) &ca_cert_blob, ca_cert_blob_len); if (cert == NULL) { BIO *bio = BIO_new_mem_buf(ca_cert_blob, ca_cert_blob_len); if (bio) { cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); BIO_free(bio); } if (!cert) { tls_show_errors(MSG_WARNING, __func__, "Failed to parse ca_cert_blob"); return -1; } while (ERR_get_error()) { /* Ignore errors from DER conversion. */ } } if (!X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx), cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert_blob to " "certificate store"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " "cert already in hash table error", __func__); } else { X509_free(cert); return -1; } } X509_free(cert); wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob " "to certificate store", __func__); return 0; } #ifdef ANDROID /* Single alias */ if (ca_cert && os_strncmp("keystore://", ca_cert, 11) == 0) { if (tls_add_ca_from_keystore(SSL_CTX_get_cert_store(ssl_ctx), &ca_cert[11]) < 0) return -1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); return 0; } /* Multiple aliases separated by space */ if (ca_cert && os_strncmp("keystores://", ca_cert, 12) == 0) { char *aliases = os_strdup(&ca_cert[12]); const char *delim = " "; int rc = 0; char *savedptr; char *alias; if (!aliases) return -1; alias = strtok_r(aliases, delim, &savedptr); for (; alias; alias = strtok_r(NULL, delim, &savedptr)) { if (tls_add_ca_from_keystore_encoded( SSL_CTX_get_cert_store(ssl_ctx), alias)) { wpa_printf(MSG_WARNING, "OpenSSL: %s - Failed to add ca_cert %s from keystore", __func__, alias); rc = -1; break; } } os_free(aliases); if (rc) return rc; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); return 0; } #endif /* ANDROID */ #ifdef CONFIG_NATIVE_WINDOWS if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from " "system certificate store"); return 0; } #endif /* CONFIG_NATIVE_WINDOWS */ if (ca_cert || ca_path) { #ifndef OPENSSL_NO_STDIO if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); if (ca_cert && tls_load_ca_der(data, ca_cert) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded " "DER format CA certificate", __func__); } else return -1; } else { wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); tls_get_errors(data); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } else { /* No ca_cert configured - do not try to verify server * certificate */ conn->ca_cert_verify = 0; } return 0; } static int tls_global_ca_cert(struct tls_data *data, const char *ca_cert) { SSL_CTX *ssl_ctx = data->ssl; if (ca_cert) { if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); return -1; } wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); #ifndef OPENSSL_NO_STDIO /* Add the same CAs to the client certificate requests */ SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(ca_cert)); #endif /* OPENSSL_NO_STDIO */ os_free(data->ca_cert); data->ca_cert = os_strdup(ca_cert); } return 0; } int tls_global_set_verify(void *ssl_ctx, int check_crl, int strict) { int flags; if (check_crl) { struct tls_data *data = ssl_ctx; X509_STORE *cs = SSL_CTX_get_cert_store(data->ssl); if (cs == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to get " "certificate store when enabling " "check_crl"); return -1; } flags = X509_V_FLAG_CRL_CHECK; if (check_crl == 2) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(cs, flags); data->check_crl = check_crl; data->check_crl_strict = strict; os_get_reltime(&data->crl_last_reload); } return 0; } static int tls_connection_set_subject_match(struct tls_connection *conn, const char *subject_match, const char *altsubject_match, const char *suffix_match, const char *domain_match, const char *check_cert_subject) { os_free(conn->subject_match); conn->subject_match = NULL; if (subject_match) { conn->subject_match = os_strdup(subject_match); if (conn->subject_match == NULL) return -1; } os_free(conn->altsubject_match); conn->altsubject_match = NULL; if (altsubject_match) { conn->altsubject_match = os_strdup(altsubject_match); if (conn->altsubject_match == NULL) return -1; } os_free(conn->suffix_match); conn->suffix_match = NULL; if (suffix_match) { conn->suffix_match = os_strdup(suffix_match); if (conn->suffix_match == NULL) return -1; } os_free(conn->domain_match); conn->domain_match = NULL; if (domain_match) { conn->domain_match = os_strdup(domain_match); if (conn->domain_match == NULL) return -1; } os_free(conn->check_cert_subject); conn->check_cert_subject = NULL; if (check_cert_subject) { conn->check_cert_subject = os_strdup(check_cert_subject); if (!conn->check_cert_subject) return -1; } return 0; } #ifdef CONFIG_SUITEB #if OPENSSL_VERSION_NUMBER >= 0x10002000L static int suiteb_cert_cb(SSL *ssl, void *arg) { struct tls_connection *conn = arg; /* * This cert_cb() is not really the best location for doing a * constraint check for the ServerKeyExchange message, but this seems to * be the only place where the current OpenSSL sequence can be * terminated cleanly with an TLS alert going out to the server. */ if (!(conn->flags & TLS_CONN_SUITEB)) return 1; /* DHE is enabled only with DHE-RSA-AES256-GCM-SHA384 */ if (conn->cipher_suite != 0x9f) return 1; if (conn->server_dh_prime_len >= 3072) return 1; wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length (%d bits) not sufficient for Suite B RSA - reject handshake", conn->server_dh_prime_len); return 0; } #endif /* OPENSSL_VERSION_NUMBER */ #endif /* CONFIG_SUITEB */ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags, const char *openssl_ciphers) { SSL *ssl = conn->ssl; #ifdef SSL_OP_NO_TICKET if (flags & TLS_CONN_DISABLE_SESSION_TICKET) SSL_set_options(ssl, SSL_OP_NO_TICKET); else SSL_clear_options(ssl, SSL_OP_NO_TICKET); #endif /* SSL_OP_NO_TICKET */ #ifdef SSL_OP_NO_TLSv1 if (flags & TLS_CONN_DISABLE_TLSv1_0) SSL_set_options(ssl, SSL_OP_NO_TLSv1); else SSL_clear_options(ssl, SSL_OP_NO_TLSv1); #endif /* SSL_OP_NO_TLSv1 */ #ifdef SSL_OP_NO_TLSv1_1 if (flags & TLS_CONN_DISABLE_TLSv1_1) SSL_set_options(ssl, SSL_OP_NO_TLSv1_1); else SSL_clear_options(ssl, SSL_OP_NO_TLSv1_1); #endif /* SSL_OP_NO_TLSv1_1 */ #ifdef SSL_OP_NO_TLSv1_2 if (flags & TLS_CONN_DISABLE_TLSv1_2) SSL_set_options(ssl, SSL_OP_NO_TLSv1_2); else SSL_clear_options(ssl, SSL_OP_NO_TLSv1_2); #endif /* SSL_OP_NO_TLSv1_2 */ #ifdef SSL_OP_NO_TLSv1_3 if (flags & TLS_CONN_DISABLE_TLSv1_3) SSL_set_options(ssl, SSL_OP_NO_TLSv1_3); else SSL_clear_options(ssl, SSL_OP_NO_TLSv1_3); #endif /* SSL_OP_NO_TLSv1_3 */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L if (flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1 | TLS_CONN_ENABLE_TLSv1_2)) { int version = 0; /* Explicit request to enable TLS versions even if needing to * override systemwide policies. */ if (flags & TLS_CONN_ENABLE_TLSv1_0) version = TLS1_VERSION; else if (flags & TLS_CONN_ENABLE_TLSv1_1) version = TLS1_1_VERSION; else if (flags & TLS_CONN_ENABLE_TLSv1_2) version = TLS1_2_VERSION; if (!version) { wpa_printf(MSG_DEBUG, "OpenSSL: Invalid TLS version configuration"); return -1; } if (SSL_set_min_proto_version(ssl, version) != 1) { wpa_printf(MSG_DEBUG, "OpenSSL: Failed to set minimum TLS version"); return -1; } } #endif /* >= 1.1.0 */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) && \ !defined(OPENSSL_IS_BORINGSSL) - if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) && - SSL_get_security_level(ssl) >= 2) { - /* - * Need to drop to security level 1 to allow TLS versions older - * than 1.2 to be used when explicitly enabled in configuration. - */ - SSL_set_security_level(conn->ssl, 1); + { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + int need_level = 0; +#else + int need_level = 1; +#endif + + if ((flags & + (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) && + SSL_get_security_level(ssl) > need_level) { + /* + * Need to drop to security level 1 (or 0 with OpenSSL + * 3.0) to allow TLS versions older than 1.2 to be used + * when explicitly enabled in configuration. + */ + SSL_set_security_level(conn->ssl, need_level); + } } #endif #ifdef CONFIG_SUITEB #ifdef OPENSSL_IS_BORINGSSL /* Start with defaults from BoringSSL */ SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, NULL, 0); #endif /* OPENSSL_IS_BORINGSSL */ #if OPENSSL_VERSION_NUMBER >= 0x10002000L if (flags & TLS_CONN_SUITEB_NO_ECDH) { const char *ciphers = "DHE-RSA-AES256-GCM-SHA384"; if (openssl_ciphers) { wpa_printf(MSG_DEBUG, "OpenSSL: Override ciphers for Suite B (no ECDH): %s", openssl_ciphers); ciphers = openssl_ciphers; } if (SSL_set_cipher_list(ssl, ciphers) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B ciphers"); return -1; } } else if (flags & TLS_CONN_SUITEB) { EC_KEY *ecdh; const char *ciphers = "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384"; int nid[1] = { NID_secp384r1 }; if (openssl_ciphers) { wpa_printf(MSG_DEBUG, "OpenSSL: Override ciphers for Suite B: %s", openssl_ciphers); ciphers = openssl_ciphers; } if (SSL_set_cipher_list(ssl, ciphers) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B ciphers"); return -1; } if (SSL_set1_curves(ssl, nid, 1) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B curves"); return -1; } ecdh = EC_KEY_new_by_curve_name(NID_secp384r1); if (!ecdh || SSL_set_tmp_ecdh(ssl, ecdh) != 1) { EC_KEY_free(ecdh); wpa_printf(MSG_INFO, "OpenSSL: Failed to set ECDH parameter"); return -1; } EC_KEY_free(ecdh); } if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) { #ifdef OPENSSL_IS_BORINGSSL uint16_t sigalgs[1] = { SSL_SIGN_RSA_PKCS1_SHA384 }; if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs, 1) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B sigalgs"); return -1; } #else /* OPENSSL_IS_BORINGSSL */ /* ECDSA+SHA384 if need to add EC support here */ if (SSL_set1_sigalgs_list(ssl, "RSA+SHA384") != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B sigalgs"); return -1; } #endif /* OPENSSL_IS_BORINGSSL */ SSL_set_options(ssl, SSL_OP_NO_TLSv1); SSL_set_options(ssl, SSL_OP_NO_TLSv1_1); SSL_set_cert_cb(ssl, suiteb_cert_cb, conn); } #else /* OPENSSL_VERSION_NUMBER < 0x10002000L */ if (flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) { wpa_printf(MSG_ERROR, "OpenSSL: Suite B RSA case not supported with this OpenSSL version"); return -1; } #endif /* OPENSSL_VERSION_NUMBER */ #ifdef OPENSSL_IS_BORINGSSL if (openssl_ciphers && os_strcmp(openssl_ciphers, "SUITEB192") == 0) { uint16_t sigalgs[1] = { SSL_SIGN_ECDSA_SECP384R1_SHA384 }; int nid[1] = { NID_secp384r1 }; if (SSL_set1_curves(ssl, nid, 1) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B curves"); return -1; } if (SSL_CTX_set_verify_algorithm_prefs(conn->ssl_ctx, sigalgs, 1) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set Suite B sigalgs"); return -1; } } #else /* OPENSSL_IS_BORINGSSL */ if (!(flags & (TLS_CONN_SUITEB | TLS_CONN_SUITEB_NO_ECDH)) && openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set openssl_ciphers '%s'", openssl_ciphers); return -1; } #endif /* OPENSSL_IS_BORINGSSL */ #else /* CONFIG_SUITEB */ if (openssl_ciphers && SSL_set_cipher_list(ssl, openssl_ciphers) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set openssl_ciphers '%s'", openssl_ciphers); return -1; } #endif /* CONFIG_SUITEB */ if (flags & TLS_CONN_TEAP_ANON_DH) { #ifndef TEAP_DH_ANON_CS #define TEAP_DH_ANON_CS \ "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:" \ "ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:" \ "ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:" \ "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \ "DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:" \ "DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:" \ "ADH-AES256-GCM-SHA384:ADH-AES128-GCM-SHA256:" \ "ADH-AES256-SHA256:ADH-AES128-SHA256:ADH-AES256-SHA:ADH-AES128-SHA" #endif static const char *cs = TEAP_DH_ANON_CS; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) && \ !defined(OPENSSL_IS_BORINGSSL) /* * Need to drop to security level 0 to allow anonymous * cipher suites for EAP-TEAP. */ SSL_set_security_level(conn->ssl, 0); #endif wpa_printf(MSG_DEBUG, "OpenSSL: Enable cipher suites for anonymous EAP-TEAP provisioning: %s", cs); if (SSL_set_cipher_list(conn->ssl, cs) != 1) { tls_show_errors(MSG_INFO, __func__, "Cipher suite configuration failed"); return -1; } } return 0; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer, unsigned int flags, const u8 *session_ctx, size_t session_ctx_len) { static int counter = 0; struct tls_data *data = ssl_ctx; if (conn == NULL) return -1; if (verify_peer == 2) { conn->ca_cert_verify = 1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); } else if (verify_peer) { conn->ca_cert_verify = 1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); } else { conn->ca_cert_verify = 0; SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); } if (tls_set_conn_flags(conn, flags, NULL) < 0) return -1; conn->flags = flags; SSL_set_accept_state(conn->ssl); if (data->tls_session_lifetime == 0) { /* * Set session id context to a unique value to make sure * session resumption cannot be used either through session * caching or TLS ticket extension. */ counter++; SSL_set_session_id_context(conn->ssl, (const unsigned char *) &counter, sizeof(counter)); } else if (session_ctx) { SSL_set_session_id_context(conn->ssl, session_ctx, session_ctx_len); } return 0; } static int tls_connection_client_cert(struct tls_connection *conn, const char *client_cert, const u8 *client_cert_blob, size_t client_cert_blob_len) { if (client_cert == NULL && client_cert_blob == NULL) return 0; #ifdef PKCS12_FUNCS #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER) /* * Clear previously set extra chain certificates, if any, from PKCS#12 * processing in tls_parse_pkcs12() to allow OpenSSL to build a new * chain properly. */ SSL_CTX_clear_extra_chain_certs(conn->ssl_ctx); #endif /* OPENSSL_VERSION_NUMBER < 0x10002000L */ #endif /* PKCS12_FUNCS */ if (client_cert_blob && SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob, client_cert_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> " "OK"); return 0; } else if (client_cert_blob) { #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20901000L tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_ASN1 failed"); #else BIO *bio; X509 *x509; tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_ASN1 failed"); bio = BIO_new(BIO_s_mem()); if (!bio) return -1; BIO_write(bio, client_cert_blob, client_cert_blob_len); x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (!x509 || SSL_use_certificate(conn->ssl, x509) != 1) { X509_free(x509); BIO_free(bio); return -1; } X509_free(x509); wpa_printf(MSG_DEBUG, "OpenSSL: Found PEM encoded certificate from blob"); while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL))) { wpa_printf(MSG_DEBUG, "OpenSSL: Added an additional certificate into the chain"); SSL_add0_chain_cert(conn->ssl, x509); } BIO_free(bio); return 0; #endif } if (client_cert == NULL) return -1; #ifdef ANDROID if (os_strncmp("keystore://", client_cert, 11) == 0) { BIO *bio = BIO_from_keystore(&client_cert[11]); X509 *x509 = NULL; int ret = -1; if (bio) { x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); } if (x509) { if (SSL_use_certificate(conn->ssl, x509) == 1) ret = 0; X509_free(x509); } /* Read additional certificates into the chain. */ while (bio) { x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (x509) { /* Takes ownership of x509 */ SSL_add0_chain_cert(conn->ssl, x509); } else { BIO_free(bio); bio = NULL; } } return ret; } #endif /* ANDROID */ #ifndef OPENSSL_NO_STDIO if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_ASN1) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)" " --> OK"); return 0; } #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) if (SSL_use_certificate_chain_file(conn->ssl, client_cert) == 1) { ERR_clear_error(); wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_chain_file" " --> OK"); return 0; } #else if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_PEM) == 1) { ERR_clear_error(); wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" " --> OK"); return 0; } #endif tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_file failed"); #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); #endif /* OPENSSL_NO_STDIO */ return -1; } static int tls_global_client_cert(struct tls_data *data, const char *client_cert) { #ifndef OPENSSL_NO_STDIO SSL_CTX *ssl_ctx = data->ssl; if (client_cert == NULL) return 0; if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_certificate_chain_file(ssl_ctx, client_cert) != 1 && SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_PEM) != 1) { tls_show_errors(MSG_INFO, __func__, "Failed to load client certificate"); return -1; } return 0; #else /* OPENSSL_NO_STDIO */ if (client_cert == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } #ifdef PKCS12_FUNCS static int tls_parse_pkcs12(struct tls_data *data, SSL *ssl, PKCS12 *p12, const char *passwd) { EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *certs; int res = 0; char buf[256]; pkey = NULL; cert = NULL; certs = NULL; if (!passwd) passwd = ""; if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { tls_show_errors(MSG_DEBUG, __func__, "Failed to parse PKCS12 file"); PKCS12_free(p12); return -1; } wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data"); if (cert) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: " "subject='%s'", buf); if (ssl) { if (SSL_use_certificate(ssl, cert) != 1) res = -1; } else { if (SSL_CTX_use_certificate(data->ssl, cert) != 1) res = -1; } X509_free(cert); } if (pkey) { wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); if (ssl) { if (SSL_use_PrivateKey(ssl, pkey) != 1) res = -1; } else { if (SSL_CTX_use_PrivateKey(data->ssl, pkey) != 1) res = -1; } EVP_PKEY_free(pkey); } if (certs) { #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) if (ssl) SSL_clear_chain_certs(ssl); else SSL_CTX_clear_chain_certs(data->ssl); while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: additional certificate" " from PKCS12: subject='%s'", buf); if ((ssl && SSL_add1_chain_cert(ssl, cert) != 1) || (!ssl && SSL_CTX_add1_chain_cert(data->ssl, cert) != 1)) { tls_show_errors(MSG_DEBUG, __func__, "Failed to add additional certificate"); res = -1; X509_free(cert); break; } X509_free(cert); } if (!res) { /* Try to continue anyway */ } sk_X509_pop_free(certs, X509_free); #ifndef OPENSSL_IS_BORINGSSL if (ssl) res = SSL_build_cert_chain( ssl, SSL_BUILD_CHAIN_FLAG_CHECK | SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR); else res = SSL_CTX_build_cert_chain( data->ssl, SSL_BUILD_CHAIN_FLAG_CHECK | SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR); if (!res) { tls_show_errors(MSG_DEBUG, __func__, "Failed to build certificate chain"); } else if (res == 2) { wpa_printf(MSG_DEBUG, "TLS: Ignore certificate chain verification error when building chain with PKCS#12 extra certificates"); } #endif /* OPENSSL_IS_BORINGSSL */ /* * Try to continue regardless of result since it is possible for * the extra certificates not to be required. */ res = 0; #else /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ SSL_CTX_clear_extra_chain_certs(data->ssl); while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: additional certificate" " from PKCS12: subject='%s'", buf); /* * There is no SSL equivalent for the chain cert - so * always add it to the context... */ if (SSL_CTX_add_extra_chain_cert(data->ssl, cert) != 1) { X509_free(cert); res = -1; break; } } sk_X509_pop_free(certs, X509_free); #endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */ } PKCS12_free(p12); if (res < 0) tls_get_errors(data); return res; } #endif /* PKCS12_FUNCS */ static int tls_read_pkcs12(struct tls_data *data, SSL *ssl, const char *private_key, const char *passwd) { #ifdef PKCS12_FUNCS FILE *f; PKCS12 *p12; f = fopen(private_key, "rb"); if (f == NULL) return -1; p12 = d2i_PKCS12_fp(f, NULL); fclose(f); if (p12 == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to use PKCS#12 file"); return -1; } return tls_parse_pkcs12(data, ssl, p12, passwd); #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " "p12/pfx files"); return -1; #endif /* PKCS12_FUNCS */ } static int tls_read_pkcs12_blob(struct tls_data *data, SSL *ssl, const u8 *blob, size_t len, const char *passwd) { #ifdef PKCS12_FUNCS PKCS12 *p12; p12 = d2i_PKCS12(NULL, (const unsigned char **) &blob, len); if (p12 == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to use PKCS#12 blob"); return -1; } return tls_parse_pkcs12(data, ssl, p12, passwd); #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse " "p12/pfx blobs"); return -1; #endif /* PKCS12_FUNCS */ } #ifndef OPENSSL_NO_ENGINE static int tls_engine_get_cert(struct tls_connection *conn, const char *cert_id, X509 **cert) { /* this runs after the private key is loaded so no PIN is required */ struct { const char *cert_id; X509 *cert; } params; params.cert_id = cert_id; params.cert = NULL; if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) { unsigned long err = ERR_get_error(); wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id" " '%s' [%s]", cert_id, ERR_error_string(err, NULL)); if (tls_is_pin_error(err)) return TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN; return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } if (!params.cert) { wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id" " '%s'", cert_id); return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } *cert = params.cert; return 0; } #endif /* OPENSSL_NO_ENGINE */ static int tls_connection_engine_client_cert(struct tls_connection *conn, const char *cert_id) { #ifndef OPENSSL_NO_ENGINE X509 *cert; if (tls_engine_get_cert(conn, cert_id, &cert)) return -1; if (!SSL_use_certificate(conn->ssl, cert)) { tls_show_errors(MSG_ERROR, __func__, "SSL_use_certificate failed"); X509_free(cert); return -1; } X509_free(cert); wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> " "OK"); return 0; #else /* OPENSSL_NO_ENGINE */ return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_engine_ca_cert(struct tls_data *data, struct tls_connection *conn, const char *ca_cert_id) { #ifndef OPENSSL_NO_ENGINE X509 *cert; SSL_CTX *ssl_ctx = data->ssl; X509_STORE *store; if (tls_engine_get_cert(conn, ca_cert_id, &cert)) return -1; /* start off the same as tls_connection_ca_cert */ store = X509_STORE_new(); if (store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); X509_free(cert); return -1; } SSL_CTX_set_cert_store(ssl_ctx, store); if (!X509_STORE_add_cert(store, cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add CA certificate from engine " "to certificate store"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert" " already in hash table error", __func__); } else { X509_free(cert); return -1; } } X509_free(cert); wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine " "to certificate store", __func__); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); conn->ca_cert_verify = 1; return 0; #else /* OPENSSL_NO_ENGINE */ return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_engine_private_key(struct tls_connection *conn) { #if defined(ANDROID) || !defined(OPENSSL_NO_ENGINE) if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { tls_show_errors(MSG_ERROR, __func__, "ENGINE: cannot use private key for TLS"); return -1; } if (!SSL_check_private_key(conn->ssl)) { tls_show_errors(MSG_INFO, __func__, "Private key failed verification"); return -1; } return 0; #else /* OPENSSL_NO_ENGINE */ wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but " "engine support was not compiled in"); return -1; #endif /* OPENSSL_NO_ENGINE */ } #ifndef OPENSSL_NO_STDIO static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) { if (!password) return 0; os_strlcpy(buf, (const char *) password, size); return os_strlen(buf); } #endif /* OPENSSL_NO_STDIO */ static int tls_use_private_key_file(struct tls_data *data, SSL *ssl, const char *private_key, const char *private_key_passwd) { #ifndef OPENSSL_NO_STDIO BIO *bio; EVP_PKEY *pkey; int ret; /* First try ASN.1 (DER). */ bio = BIO_new_file(private_key, "r"); if (!bio) return -1; pkey = d2i_PrivateKey_bio(bio, NULL); BIO_free(bio); if (pkey) { wpa_printf(MSG_DEBUG, "OpenSSL: %s (DER) --> loaded", __func__); } else { /* Try PEM with the provided password. */ bio = BIO_new_file(private_key, "r"); if (!bio) return -1; pkey = PEM_read_bio_PrivateKey(bio, NULL, tls_passwd_cb, (void *) private_key_passwd); BIO_free(bio); if (!pkey) return -1; wpa_printf(MSG_DEBUG, "OpenSSL: %s (PEM) --> loaded", __func__); /* Clear errors from the previous failed load. */ ERR_clear_error(); } if (ssl) ret = SSL_use_PrivateKey(ssl, pkey); else ret = SSL_CTX_use_PrivateKey(data->ssl, pkey); EVP_PKEY_free(pkey); return ret == 1 ? 0 : -1; #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } static int tls_connection_private_key(struct tls_data *data, struct tls_connection *conn, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len) { BIO *bio; int ok; if (private_key == NULL && private_key_blob == NULL) return 0; ok = 0; while (private_key_blob) { if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" "ASN1(EVP_PKEY_RSA) --> OK"); ok = 1; break; } if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" "ASN1(EVP_PKEY_DSA) --> OK"); ok = 1; break; } #ifndef OPENSSL_NO_EC if (SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_ASN1(EVP_PKEY_EC) --> OK"); ok = 1; break; } #endif /* OPENSSL_NO_EC */ if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_RSAPrivateKey_ASN1 --> OK"); ok = 1; break; } bio = BIO_new_mem_buf((u8 *) private_key_blob, private_key_blob_len); if (bio) { EVP_PKEY *pkey; pkey = PEM_read_bio_PrivateKey( bio, NULL, tls_passwd_cb, (void *) private_key_passwd); if (pkey) { if (SSL_use_PrivateKey(conn->ssl, pkey) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey --> OK"); ok = 1; EVP_PKEY_free(pkey); BIO_free(bio); break; } EVP_PKEY_free(pkey); } BIO_free(bio); } if (tls_read_pkcs12_blob(data, conn->ssl, private_key_blob, private_key_blob_len, private_key_passwd) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> " "OK"); ok = 1; break; } break; } while (!ok && private_key) { if (tls_use_private_key_file(data, conn->ssl, private_key, private_key_passwd) == 0) { ok = 1; break; } if (tls_read_pkcs12(data, conn->ssl, private_key, private_key_passwd) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file " "--> OK"); ok = 1; break; } if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to " "access certificate store --> OK"); ok = 1; break; } break; } if (!ok) { tls_show_errors(MSG_INFO, __func__, "Failed to load private key"); return -1; } ERR_clear_error(); if (!SSL_check_private_key(conn->ssl)) { tls_show_errors(MSG_INFO, __func__, "Private key failed " "verification"); return -1; } wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully"); return 0; } static int tls_global_private_key(struct tls_data *data, const char *private_key, const char *private_key_passwd) { SSL_CTX *ssl_ctx = data->ssl; if (private_key == NULL) return 0; if (tls_use_private_key_file(data, NULL, private_key, private_key_passwd) && tls_read_pkcs12(data, NULL, private_key, private_key_passwd)) { tls_show_errors(MSG_INFO, __func__, "Failed to load private key"); ERR_clear_error(); return -1; } ERR_clear_error(); if (!SSL_CTX_check_private_key(ssl_ctx)) { tls_show_errors(MSG_INFO, __func__, "Private key failed verification"); return -1; } return 0; } static int tls_connection_dh(struct tls_connection *conn, const char *dh_file) { #ifdef OPENSSL_NO_DH if (dh_file == NULL) return 0; wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " "dh_file specified"); return -1; #else /* OPENSSL_NO_DH */ DH *dh; BIO *bio; /* TODO: add support for dh_blob */ if (dh_file == NULL) return 0; if (conn == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); #ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; } #endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_set_tmp_dh(conn->ssl, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0; #endif /* OPENSSL_NO_DH */ } static int tls_global_dh(struct tls_data *data, const char *dh_file) { #ifdef OPENSSL_NO_DH if (dh_file == NULL) return 0; wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " "dh_file specified"); return -1; #else /* OPENSSL_NO_DH */ SSL_CTX *ssl_ctx = data->ssl; DH *dh; BIO *bio; /* TODO: add support for dh_blob */ if (dh_file == NULL) return 0; if (ssl_ctx == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); #ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; } #endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0; #endif /* OPENSSL_NO_DH */ } int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn, struct tls_random *keys) { SSL *ssl; if (conn == NULL || keys == NULL) return -1; ssl = conn->ssl; if (ssl == NULL) return -1; os_memset(keys, 0, sizeof(*keys)); keys->client_random = conn->client_random; keys->client_random_len = SSL_get_client_random( ssl, conn->client_random, sizeof(conn->client_random)); keys->server_random = conn->server_random; keys->server_random_len = SSL_get_server_random( ssl, conn->server_random, sizeof(conn->server_random)); return 0; } #ifdef OPENSSL_NEED_EAP_FAST_PRF static int openssl_get_keyblock_size(SSL *ssl) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) const EVP_CIPHER *c; const EVP_MD *h; int md_size; if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL || ssl->read_hash == NULL) return -1; c = ssl->enc_read_ctx->cipher; h = EVP_MD_CTX_md(ssl->read_hash); if (h) md_size = EVP_MD_size(h); else if (ssl->s3) md_size = ssl->s3->tmp.new_mac_secret_size; else return -1; wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: key_len=%d MD_size=%d " "IV_len=%d", EVP_CIPHER_key_length(c), md_size, EVP_CIPHER_iv_length(c)); return 2 * (EVP_CIPHER_key_length(c) + md_size + EVP_CIPHER_iv_length(c)); #else const SSL_CIPHER *ssl_cipher; int cipher, digest; const EVP_CIPHER *c; const EVP_MD *h; int mac_key_len, enc_key_len, fixed_iv_len; ssl_cipher = SSL_get_current_cipher(ssl); if (!ssl_cipher) return -1; cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher); digest = SSL_CIPHER_get_digest_nid(ssl_cipher); wpa_printf(MSG_DEBUG, "OpenSSL: cipher nid %d digest nid %d", cipher, digest); if (cipher < 0 || digest < 0) return -1; if (cipher == NID_undef) { wpa_printf(MSG_DEBUG, "OpenSSL: no cipher in use?!"); return -1; } c = EVP_get_cipherbynid(cipher); if (!c) return -1; enc_key_len = EVP_CIPHER_key_length(c); if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE || EVP_CIPHER_mode(c) == EVP_CIPH_CCM_MODE) fixed_iv_len = 4; /* only part of IV from PRF */ else fixed_iv_len = EVP_CIPHER_iv_length(c); if (digest == NID_undef) { wpa_printf(MSG_DEBUG, "OpenSSL: no digest in use (e.g., AEAD)"); mac_key_len = 0; } else { h = EVP_get_digestbynid(digest); if (!h) return -1; mac_key_len = EVP_MD_size(h); } wpa_printf(MSG_DEBUG, "OpenSSL: keyblock size: mac_key_len=%d enc_key_len=%d fixed_iv_len=%d", mac_key_len, enc_key_len, fixed_iv_len); return 2 * (mac_key_len + enc_key_len + fixed_iv_len); #endif } #endif /* OPENSSL_NEED_EAP_FAST_PRF */ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, const char *label, const u8 *context, size_t context_len, u8 *out, size_t out_len) { if (!conn || SSL_export_keying_material(conn->ssl, out, out_len, label, os_strlen(label), context, context_len, context != NULL) != 1) return -1; return 0; } int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, u8 *out, size_t out_len) { #ifdef OPENSSL_NEED_EAP_FAST_PRF SSL *ssl; SSL_SESSION *sess; u8 *rnd; int ret = -1; int skip = 0; u8 *tmp_out = NULL; u8 *_out = out; unsigned char client_random[SSL3_RANDOM_SIZE]; unsigned char server_random[SSL3_RANDOM_SIZE]; unsigned char master_key[64]; size_t master_key_len; const char *ver; /* * TLS library did not support EAP-FAST key generation, so get the * needed TLS session parameters and use an internal implementation of * TLS PRF to derive the key. */ if (conn == NULL) return -1; ssl = conn->ssl; if (ssl == NULL) return -1; ver = SSL_get_version(ssl); sess = SSL_get_session(ssl); if (!ver || !sess) return -1; skip = openssl_get_keyblock_size(ssl); if (skip < 0) return -1; tmp_out = os_malloc(skip + out_len); if (!tmp_out) return -1; _out = tmp_out; rnd = os_malloc(2 * SSL3_RANDOM_SIZE); if (!rnd) { os_free(tmp_out); return -1; } SSL_get_client_random(ssl, client_random, sizeof(client_random)); SSL_get_server_random(ssl, server_random, sizeof(server_random)); master_key_len = SSL_SESSION_get_master_key(sess, master_key, sizeof(master_key)); os_memcpy(rnd, server_random, SSL3_RANDOM_SIZE); os_memcpy(rnd + SSL3_RANDOM_SIZE, client_random, SSL3_RANDOM_SIZE); if (os_strcmp(ver, "TLSv1.2") == 0) { tls_prf_sha256(master_key, master_key_len, "key expansion", rnd, 2 * SSL3_RANDOM_SIZE, _out, skip + out_len); ret = 0; } else if (tls_prf_sha1_md5(master_key, master_key_len, "key expansion", rnd, 2 * SSL3_RANDOM_SIZE, _out, skip + out_len) == 0) { ret = 0; } forced_memzero(master_key, sizeof(master_key)); os_free(rnd); if (ret == 0) os_memcpy(out, _out + skip, out_len); bin_clear_free(tmp_out, skip); return ret; #else /* OPENSSL_NEED_EAP_FAST_PRF */ wpa_printf(MSG_ERROR, "OpenSSL: EAP-FAST keys cannot be exported in FIPS mode"); return -1; #endif /* OPENSSL_NEED_EAP_FAST_PRF */ } static struct wpabuf * openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *out_data; /* * Give TLS handshake data from the server (if available) to OpenSSL * for processing. */ if (in_data && wpabuf_len(in_data) > 0 && BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)) < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_write"); return NULL; } /* Initiate TLS handshake or continue the existing handshake */ if (conn->server) res = SSL_accept(conn->ssl); else res = SSL_connect(conn->ssl); if (res != 1) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want " "more data"); else if (err == SSL_ERROR_WANT_WRITE) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to " "write"); else { tls_show_errors(MSG_INFO, __func__, "SSL_connect"); conn->failed++; if (!conn->server && !conn->client_hello_generated) { /* The server would not understand TLS Alert * before ClientHello, so simply terminate * handshake on this type of error case caused * by a likely internal error like no ciphers * available. */ wpa_printf(MSG_DEBUG, "OpenSSL: Could not generate ClientHello"); conn->write_alerts++; return NULL; } } } if (!conn->server && !conn->failed) conn->client_hello_generated = 1; #ifdef CONFIG_SUITEB if ((conn->flags & TLS_CONN_SUITEB) && !conn->server && os_strncmp(SSL_get_cipher(conn->ssl), "DHE-", 4) == 0 && conn->server_dh_prime_len < 3072) { struct tls_context *context = conn->context; /* * This should not be reached since earlier cert_cb should have * terminated the handshake. Keep this check here for extra * protection if anything goes wrong with the more low-level * checks based on having to parse the TLS handshake messages. */ wpa_printf(MSG_DEBUG, "OpenSSL: Server DH prime length: %d bits", conn->server_dh_prime_len); if (context->event_cb) { union tls_event_data ev; os_memset(&ev, 0, sizeof(ev)); ev.alert.is_local = 1; ev.alert.type = "fatal"; ev.alert.description = "insufficient security"; context->event_cb(context->cb_ctx, TLS_ALERT, &ev); } /* * Could send a TLS Alert to the server, but for now, simply * terminate handshake. */ conn->failed++; conn->write_alerts++; return NULL; } #endif /* CONFIG_SUITEB */ /* Get the TLS handshake data to be sent to the server */ res = BIO_ctrl_pending(conn->ssl_out); wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); out_data = wpabuf_alloc(res); if (out_data == NULL) { wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " "handshake output (%d bytes)", res); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } return NULL; } res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data), res); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_read"); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } wpabuf_free(out_data); return NULL; } wpabuf_put(out_data, res); return out_data; } static struct wpabuf * openssl_get_appl_data(struct tls_connection *conn, size_t max_len) { struct wpabuf *appl_data; int res; appl_data = wpabuf_alloc(max_len + 100); if (appl_data == NULL) return NULL; res = SSL_read(conn->ssl, wpabuf_mhead(appl_data), wpabuf_size(appl_data)); if (res < 0) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { wpa_printf(MSG_DEBUG, "SSL: No Application Data " "included"); } else { tls_show_errors(MSG_INFO, __func__, "Failed to read possible " "Application Data"); } wpabuf_free(appl_data); return NULL; } wpabuf_put(appl_data, res); wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished " "message", appl_data); return appl_data; } static struct wpabuf * openssl_connection_handshake(struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct wpabuf *out_data; if (appl_data) *appl_data = NULL; out_data = openssl_handshake(conn, in_data); if (out_data == NULL) return NULL; if (conn->invalid_hb_used) { wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response"); wpabuf_free(out_data); return NULL; } if (SSL_is_init_finished(conn->ssl)) { wpa_printf(MSG_DEBUG, "OpenSSL: Handshake finished - resumed=%d", tls_connection_resumed(conn->ssl_ctx, conn)); if (conn->server) { char *buf; size_t buflen = 2000; buf = os_malloc(buflen); if (buf) { if (SSL_get_shared_ciphers(conn->ssl, buf, buflen)) { buf[buflen - 1] = '\0'; wpa_printf(MSG_DEBUG, "OpenSSL: Shared ciphers: %s", buf); } os_free(buf); } } if (appl_data && in_data) *appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data)); } if (conn->invalid_hb_used) { wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response"); if (appl_data) { wpabuf_free(*appl_data); *appl_data = NULL; } wpabuf_free(out_data); return NULL; } return out_data; } struct wpabuf * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return openssl_connection_handshake(conn, in_data, appl_data); } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { conn->server = 1; return openssl_connection_handshake(conn, in_data, appl_data); } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *buf; if (conn == NULL) return NULL; /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */ if ((res = BIO_reset(conn->ssl_in)) < 0 || (res = BIO_reset(conn->ssl_out)) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - SSL_write"); return NULL; } /* Read encrypted data to be sent to the server */ buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - BIO_read"); wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *buf; /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ res = BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - BIO_write"); return NULL; } if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } /* Read decrypted data for further processing */ /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ) { wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want more data"); res = 0; } else { tls_show_errors(MSG_INFO, __func__, "Decryption failed - SSL_read"); wpabuf_free(buf); return NULL; } } wpabuf_put(buf, res); if (conn->invalid_hb_used) { wpa_printf(MSG_INFO, "TLS: Heartbeat attack detected - do not send response"); wpabuf_free(buf); return NULL; } return buf; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { return conn ? SSL_session_reused(conn->ssl) : 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { char buf[500], *pos, *end; u8 *c; int ret; if (conn == NULL || conn->ssl == NULL || ciphers == NULL) return -1; buf[0] = '\0'; pos = buf; end = pos + sizeof(buf); c = ciphers; while (*c != TLS_CIPHER_NONE) { const char *suite; switch (*c) { case TLS_CIPHER_RC4_SHA: suite = "RC4-SHA"; break; case TLS_CIPHER_AES128_SHA: suite = "AES128-SHA"; break; case TLS_CIPHER_RSA_DHE_AES128_SHA: suite = "DHE-RSA-AES128-SHA"; break; case TLS_CIPHER_ANON_DH_AES128_SHA: suite = "ADH-AES128-SHA"; break; case TLS_CIPHER_RSA_DHE_AES256_SHA: suite = "DHE-RSA-AES256-SHA"; break; case TLS_CIPHER_AES256_SHA: suite = "AES256-SHA"; break; default: wpa_printf(MSG_DEBUG, "TLS: Unsupported " "cipher selection: %d", *c); return -1; } ret = os_snprintf(pos, end - pos, ":%s", suite); if (os_snprintf_error(end - pos, ret)) break; pos += ret; c++; } if (!buf[0]) { wpa_printf(MSG_DEBUG, "OpenSSL: No ciphers listed"); return -1; } wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) #ifdef EAP_FAST_OR_TEAP if (os_strstr(buf, ":ADH-")) { /* * Need to drop to security level 0 to allow anonymous * cipher suites for EAP-FAST. */ SSL_set_security_level(conn->ssl, 0); } else if (SSL_get_security_level(conn->ssl) == 0) { /* Force at least security level 1 */ SSL_set_security_level(conn->ssl, 1); } #endif /* EAP_FAST_OR_TEAP */ #endif if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) { tls_show_errors(MSG_INFO, __func__, "Cipher suite configuration failed"); return -1; } return 0; } int tls_get_version(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { const char *name; if (conn == NULL || conn->ssl == NULL) return -1; name = SSL_get_version(conn->ssl); if (name == NULL) return -1; os_strlcpy(buf, name, buflen); return 0; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { const char *name; if (conn == NULL || conn->ssl == NULL) return -1; name = SSL_get_cipher(conn->ssl); if (name == NULL) return -1; os_strlcpy(buf, name, buflen); return 0; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); return 0; } #ifdef EAP_FAST_OR_TEAP /* ClientHello TLS extensions require a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { if (conn == NULL || conn->ssl == NULL || ext_type != 35) return -1; if (SSL_set_session_ticket_ext(conn->ssl, (void *) data, data_len) != 1) return -1; return 0; } #endif /* EAP_FAST_OR_TEAP */ int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } #ifdef HAVE_OCSP static void ocsp_debug_print_resp(OCSP_RESPONSE *rsp) { #ifndef CONFIG_NO_STDOUT_DEBUG BIO *out; size_t rlen; char *txt; int res; if (wpa_debug_level > MSG_DEBUG) return; out = BIO_new(BIO_s_mem()); if (!out) return; OCSP_RESPONSE_print(out, rsp, 0); rlen = BIO_ctrl_pending(out); txt = os_malloc(rlen + 1); if (!txt) { BIO_free(out); return; } res = BIO_read(out, txt, rlen); if (res > 0) { txt[res] = '\0'; wpa_printf(MSG_DEBUG, "OpenSSL: OCSP Response\n%s", txt); } os_free(txt); BIO_free(out); #endif /* CONFIG_NO_STDOUT_DEBUG */ } static int ocsp_resp_cb(SSL *s, void *arg) { struct tls_connection *conn = arg; const unsigned char *p; int len, status, reason, res; OCSP_RESPONSE *rsp; OCSP_BASICRESP *basic; OCSP_CERTID *id; ASN1_GENERALIZEDTIME *produced_at, *this_update, *next_update; X509_STORE *store; STACK_OF(X509) *certs = NULL; len = SSL_get_tlsext_status_ocsp_resp(s, &p); if (!p) { wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received"); return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1; } wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", p, len); rsp = d2i_OCSP_RESPONSE(NULL, &p, len); if (!rsp) { wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSP response"); return 0; } ocsp_debug_print_resp(rsp); status = OCSP_response_status(rsp); if (status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d (%s)", status, OCSP_response_status_str(status)); return 0; } basic = OCSP_response_get1_basic(rsp); if (!basic) { wpa_printf(MSG_INFO, "OpenSSL: Could not find BasicOCSPResponse"); return 0; } store = SSL_CTX_get_cert_store(conn->ssl_ctx); if (conn->peer_issuer) { debug_print_cert(conn->peer_issuer, "Add OCSP issuer"); if (X509_STORE_add_cert(store, conn->peer_issuer) != 1) { tls_show_errors(MSG_INFO, __func__, "OpenSSL: Could not add issuer to certificate store"); } certs = sk_X509_new_null(); if (certs) { X509 *cert; cert = X509_dup(conn->peer_issuer); if (cert && !sk_X509_push(certs, cert)) { tls_show_errors( MSG_INFO, __func__, "OpenSSL: Could not add issuer to OCSP responder trust store"); X509_free(cert); sk_X509_free(certs); certs = NULL; } if (certs && conn->peer_issuer_issuer) { cert = X509_dup(conn->peer_issuer_issuer); if (cert && !sk_X509_push(certs, cert)) { tls_show_errors( MSG_INFO, __func__, "OpenSSL: Could not add issuer's issuer to OCSP responder trust store"); X509_free(cert); } } } } status = OCSP_basic_verify(basic, certs, store, OCSP_TRUSTOTHER); sk_X509_pop_free(certs, X509_free); if (status <= 0) { tls_show_errors(MSG_INFO, __func__, "OpenSSL: OCSP response failed verification"); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return 0; } wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response verification succeeded"); if (!conn->peer_cert) { wpa_printf(MSG_DEBUG, "OpenSSL: Peer certificate not available for OCSP status check"); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return 0; } if (!conn->peer_issuer) { wpa_printf(MSG_DEBUG, "OpenSSL: Peer issuer certificate not available for OCSP status check"); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return 0; } id = OCSP_cert_to_id(EVP_sha256(), conn->peer_cert, conn->peer_issuer); if (!id) { wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier (SHA256)"); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return 0; } res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at, &this_update, &next_update); if (!res) { OCSP_CERTID_free(id); id = OCSP_cert_to_id(NULL, conn->peer_cert, conn->peer_issuer); if (!id) { wpa_printf(MSG_DEBUG, "OpenSSL: Could not create OCSP certificate identifier (SHA1)"); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return 0; } res = OCSP_resp_find_status(basic, id, &status, &reason, &produced_at, &this_update, &next_update); } if (!res) { wpa_printf(MSG_INFO, "OpenSSL: Could not find current server certificate from OCSP response%s", (conn->flags & TLS_CONN_REQUIRE_OCSP) ? "" : " (OCSP not required)"); OCSP_CERTID_free(id); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return (conn->flags & TLS_CONN_REQUIRE_OCSP) ? 0 : 1; } OCSP_CERTID_free(id); if (!OCSP_check_validity(this_update, next_update, 5 * 60, -1)) { tls_show_errors(MSG_INFO, __func__, "OpenSSL: OCSP status times invalid"); OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); return 0; } OCSP_BASICRESP_free(basic); OCSP_RESPONSE_free(rsp); wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status for server certificate: %s", OCSP_cert_status_str(status)); if (status == V_OCSP_CERTSTATUS_GOOD) return 1; if (status == V_OCSP_CERTSTATUS_REVOKED) return 0; if (conn->flags & TLS_CONN_REQUIRE_OCSP) { wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP required"); return 0; } wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status unknown, but OCSP was not required, so allow connection to continue"); return 1; } static int ocsp_status_cb(SSL *s, void *arg) { char *tmp; char *resp; size_t len; if (tls_global->ocsp_stapling_response == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - no response configured"); return SSL_TLSEXT_ERR_OK; } resp = os_readfile(tls_global->ocsp_stapling_response, &len); if (resp == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - could not read response file"); /* TODO: Build OCSPResponse with responseStatus = internalError */ return SSL_TLSEXT_ERR_OK; } wpa_printf(MSG_DEBUG, "OpenSSL: OCSP status callback - send cached response"); tmp = OPENSSL_malloc(len); if (tmp == NULL) { os_free(resp); return SSL_TLSEXT_ERR_ALERT_FATAL; } os_memcpy(tmp, resp, len); os_free(resp); SSL_set_tlsext_status_ocsp_resp(s, tmp, len); return SSL_TLSEXT_ERR_OK; } #endif /* HAVE_OCSP */ static size_t max_str_len(const char **lines) { const char **p; size_t max_len = 0; for (p = lines; *p; p++) { size_t len = os_strlen(*p); if (len > max_len) max_len = len; } return max_len; } static int match_lines_in_file(const char *path, const char **lines) { FILE *f; char *buf; size_t bufsize; int found = 0, is_linestart = 1; bufsize = max_str_len(lines) + sizeof("\r\n"); buf = os_malloc(bufsize); if (!buf) return 0; f = fopen(path, "r"); if (!f) { os_free(buf); return 0; } while (!found && fgets(buf, bufsize, f)) { int is_lineend; size_t len; const char **p; len = strcspn(buf, "\r\n"); is_lineend = buf[len] != '\0'; buf[len] = '\0'; if (is_linestart && is_lineend) { for (p = lines; !found && *p; p++) found = os_strcmp(buf, *p) == 0; } is_linestart = is_lineend; } fclose(f); bin_clear_free(buf, bufsize); return found; } static int is_tpm2_key(const char *path) { /* Check both new and old format of TPM2 PEM guard tag */ static const char *tpm2_tags[] = { "-----BEGIN TSS2 PRIVATE KEY-----", "-----BEGIN TSS2 KEY BLOB-----", NULL }; return match_lines_in_file(path, tpm2_tags); } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { struct tls_data *data = tls_ctx; int ret; unsigned long err; int can_pkcs11 = 0; const char *key_id = params->key_id; const char *cert_id = params->cert_id; const char *ca_cert_id = params->ca_cert_id; const char *engine_id = params->engine ? params->engine_id : NULL; const char *ciphers; if (conn == NULL) return -1; if (params->flags & TLS_CONN_REQUIRE_OCSP_ALL) { wpa_printf(MSG_INFO, "OpenSSL: ocsp=3 not supported"); return -1; } /* * If the engine isn't explicitly configured, and any of the * cert/key fields are actually PKCS#11 URIs, then automatically * use the PKCS#11 ENGINE. */ if (!engine_id || os_strcmp(engine_id, "pkcs11") == 0) can_pkcs11 = 1; if (!key_id && params->private_key && can_pkcs11 && os_strncmp(params->private_key, "pkcs11:", 7) == 0) { can_pkcs11 = 2; key_id = params->private_key; } if (!cert_id && params->client_cert && can_pkcs11 && os_strncmp(params->client_cert, "pkcs11:", 7) == 0) { can_pkcs11 = 2; cert_id = params->client_cert; } if (!ca_cert_id && params->ca_cert && can_pkcs11 && os_strncmp(params->ca_cert, "pkcs11:", 7) == 0) { can_pkcs11 = 2; ca_cert_id = params->ca_cert; } /* If we need to automatically enable the PKCS#11 ENGINE, do so. */ if (can_pkcs11 == 2 && !engine_id) engine_id = "pkcs11"; /* If private_key points to a TPM2-wrapped key, automatically enable * tpm2 engine and use it to unwrap the key. */ if (params->private_key && (!engine_id || os_strcmp(engine_id, "tpm2") == 0) && is_tpm2_key(params->private_key)) { wpa_printf(MSG_DEBUG, "OpenSSL: Found TPM2 wrapped key %s", params->private_key); key_id = key_id ? key_id : params->private_key; engine_id = engine_id ? engine_id : "tpm2"; } #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) if (params->flags & TLS_CONN_EAP_FAST) { wpa_printf(MSG_DEBUG, "OpenSSL: Use TLSv1_method() for EAP-FAST"); if (SSL_set_ssl_method(conn->ssl, TLSv1_method()) != 1) { tls_show_errors(MSG_INFO, __func__, "Failed to set TLSv1_method() for EAP-FAST"); return -1; } } #endif #if OPENSSL_VERSION_NUMBER >= 0x10101000L #ifdef SSL_OP_NO_TLSv1_3 if (params->flags & TLS_CONN_EAP_FAST) { /* Need to disable TLS v1.3 at least for now since OpenSSL 1.1.1 * refuses to start the handshake with the modified ciphersuite * list (no TLS v1.3 ciphersuites included) for EAP-FAST. */ wpa_printf(MSG_DEBUG, "OpenSSL: Disable TLSv1.3 for EAP-FAST"); SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_3); } #endif /* SSL_OP_NO_TLSv1_3 */ #endif #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (engine_id) { wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine %s", engine_id); ret = tls_engine_init(conn, engine_id, params->pin, key_id, cert_id, ca_cert_id); if (ret) return ret; } if (tls_connection_set_subject_match(conn, params->subject_match, params->altsubject_match, params->suffix_match, params->domain_match, params->check_cert_subject)) return -1; if (engine_id && ca_cert_id) { if (tls_connection_engine_ca_cert(data, conn, ca_cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_ca_cert(data, conn, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) return -1; if (engine_id && cert_id) { if (tls_connection_engine_client_cert(conn, cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_client_cert(conn, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) return -1; if (engine_id && key_id) { wpa_printf(MSG_DEBUG, "TLS: Using private key from engine"); if (tls_connection_engine_private_key(conn)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_private_key(data, conn, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", params->private_key); return -1; } if (tls_connection_dh(conn, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } ciphers = params->openssl_ciphers; #ifdef CONFIG_SUITEB #ifdef OPENSSL_IS_BORINGSSL if (ciphers && os_strcmp(ciphers, "SUITEB192") == 0) { /* BoringSSL removed support for SUITEB192, so need to handle * this with hardcoded ciphersuite and additional checks for * other parameters. */ ciphers = "ECDHE-ECDSA-AES256-GCM-SHA384"; } #endif /* OPENSSL_IS_BORINGSSL */ #endif /* CONFIG_SUITEB */ if (ciphers && SSL_set_cipher_list(conn->ssl, ciphers) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set cipher string '%s'", ciphers); return -1; } if (!params->openssl_ecdh_curves) { #ifndef OPENSSL_IS_BORINGSSL #ifndef OPENSSL_NO_EC #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \ (OPENSSL_VERSION_NUMBER < 0x10100000L) if (SSL_set_ecdh_auto(conn->ssl, 1) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set ECDH curves to auto"); return -1; } #endif /* >= 1.0.2 && < 1.1.0 */ #endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_IS_BORINGSSL */ } else if (params->openssl_ecdh_curves[0]) { #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L) wpa_printf(MSG_INFO, "OpenSSL: ECDH configuration nnot supported"); return -1; #else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */ #ifndef OPENSSL_NO_EC if (SSL_set1_curves_list(conn->ssl, params->openssl_ecdh_curves) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set ECDH curves '%s'", params->openssl_ecdh_curves); return -1; } #else /* OPENSSL_NO_EC */ wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported"); return -1; #endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_IS_BORINGSSL */ } if (tls_set_conn_flags(conn, params->flags, params->openssl_ciphers) < 0) return -1; #ifdef OPENSSL_IS_BORINGSSL if (params->flags & TLS_CONN_REQUEST_OCSP) { SSL_enable_ocsp_stapling(conn->ssl); } #else /* OPENSSL_IS_BORINGSSL */ #ifdef HAVE_OCSP if (params->flags & TLS_CONN_REQUEST_OCSP) { SSL_CTX *ssl_ctx = data->ssl; SSL_set_tlsext_status_type(conn->ssl, TLSEXT_STATUSTYPE_ocsp); SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_resp_cb); SSL_CTX_set_tlsext_status_arg(ssl_ctx, conn); } #else /* HAVE_OCSP */ if (params->flags & TLS_CONN_REQUIRE_OCSP) { wpa_printf(MSG_INFO, "OpenSSL: No OCSP support included - reject configuration"); return -1; } if (params->flags & TLS_CONN_REQUEST_OCSP) { wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP support included - allow optional OCSP case to continue"); } #endif /* HAVE_OCSP */ #endif /* OPENSSL_IS_BORINGSSL */ conn->flags = params->flags; tls_get_errors(data); return 0; } static void openssl_debug_dump_cipher_list(SSL_CTX *ssl_ctx) { SSL *ssl; int i; ssl = SSL_new(ssl_ctx); if (!ssl) return; wpa_printf(MSG_DEBUG, "OpenSSL: Enabled cipher suites in priority order"); for (i = 0; ; i++) { const char *cipher; cipher = SSL_get_cipher_list(ssl, i); if (!cipher) break; wpa_printf(MSG_DEBUG, "Cipher %d: %s", i, cipher); } SSL_free(ssl); } #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION) static const char * openssl_pkey_type_str(const EVP_PKEY *pkey) { if (!pkey) return "NULL"; switch (EVP_PKEY_type(EVP_PKEY_id(pkey))) { case EVP_PKEY_RSA: return "RSA"; case EVP_PKEY_DSA: return "DSA"; case EVP_PKEY_DH: return "DH"; case EVP_PKEY_EC: return "EC"; } return "?"; } static void openssl_debug_dump_certificate(int i, X509 *cert) { char buf[256]; EVP_PKEY *pkey; ASN1_INTEGER *ser; char serial_num[128]; if (!cert) return; X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); ser = X509_get_serialNumber(cert); if (ser) wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num), ASN1_STRING_get0_data(ser), ASN1_STRING_length(ser)); else serial_num[0] = '\0'; pkey = X509_get_pubkey(cert); wpa_printf(MSG_DEBUG, "%d: %s (%s) %s", i, buf, openssl_pkey_type_str(pkey), serial_num); EVP_PKEY_free(pkey); } static void openssl_debug_dump_certificates(SSL_CTX *ssl_ctx) { STACK_OF(X509) *certs; wpa_printf(MSG_DEBUG, "OpenSSL: Configured certificate chain"); if (SSL_CTX_get0_chain_certs(ssl_ctx, &certs) == 1) { int i; for (i = sk_X509_num(certs); i > 0; i--) openssl_debug_dump_certificate(i, sk_X509_value(certs, i - 1)); } openssl_debug_dump_certificate(0, SSL_CTX_get0_certificate(ssl_ctx)); } #endif static void openssl_debug_dump_certificate_chains(SSL_CTX *ssl_ctx) { #if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION) int res; for (res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST); res == 1; res = SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_NEXT)) openssl_debug_dump_certificates(ssl_ctx); SSL_CTX_set_current_cert(ssl_ctx, SSL_CERT_SET_FIRST); #endif } static void openssl_debug_dump_ctx(SSL_CTX *ssl_ctx) { openssl_debug_dump_cipher_list(ssl_ctx); openssl_debug_dump_certificate_chains(ssl_ctx); } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { struct tls_data *data = tls_ctx; SSL_CTX *ssl_ctx = data->ssl; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } os_free(data->check_cert_subject); data->check_cert_subject = NULL; if (params->check_cert_subject) { data->check_cert_subject = os_strdup(params->check_cert_subject); if (!data->check_cert_subject) return -1; } if (tls_global_ca_cert(data, params->ca_cert) || tls_global_client_cert(data, params->client_cert) || tls_global_private_key(data, params->private_key, params->private_key_passwd) || tls_global_client_cert(data, params->client_cert2) || tls_global_private_key(data, params->private_key2, params->private_key_passwd2) || tls_global_dh(data, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to set global parameters"); return -1; } if (params->openssl_ciphers && SSL_CTX_set_cipher_list(ssl_ctx, params->openssl_ciphers) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set cipher string '%s'", params->openssl_ciphers); return -1; } if (!params->openssl_ecdh_curves) { #ifndef OPENSSL_IS_BORINGSSL #ifndef OPENSSL_NO_EC #if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && \ (OPENSSL_VERSION_NUMBER < 0x10100000L) if (SSL_CTX_set_ecdh_auto(ssl_ctx, 1) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set ECDH curves to auto"); return -1; } #endif /* >= 1.0.2 && < 1.1.0 */ #endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_IS_BORINGSSL */ } else if (params->openssl_ecdh_curves[0]) { #if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER < 0x10002000L) wpa_printf(MSG_INFO, "OpenSSL: ECDH configuration nnot supported"); return -1; #else /* OPENSSL_IS_BORINGSSL || < 1.0.2 */ #ifndef OPENSSL_NO_EC #if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_CTX_set_ecdh_auto(ssl_ctx, 1); #endif if (SSL_CTX_set1_curves_list(ssl_ctx, params->openssl_ecdh_curves) != 1) { wpa_printf(MSG_INFO, "OpenSSL: Failed to set ECDH curves '%s'", params->openssl_ecdh_curves); return -1; } #else /* OPENSSL_NO_EC */ wpa_printf(MSG_INFO, "OpenSSL: ECDH not supported"); return -1; #endif /* OPENSSL_NO_EC */ #endif /* OPENSSL_IS_BORINGSSL */ } #ifdef SSL_OP_NO_TICKET if (params->flags & TLS_CONN_DISABLE_SESSION_TICKET) SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TICKET); else SSL_CTX_clear_options(ssl_ctx, SSL_OP_NO_TICKET); #endif /* SSL_OP_NO_TICKET */ #ifdef HAVE_OCSP SSL_CTX_set_tlsext_status_cb(ssl_ctx, ocsp_status_cb); SSL_CTX_set_tlsext_status_arg(ssl_ctx, ssl_ctx); os_free(tls_global->ocsp_stapling_response); if (params->ocsp_stapling_response) tls_global->ocsp_stapling_response = os_strdup(params->ocsp_stapling_response); else tls_global->ocsp_stapling_response = NULL; #endif /* HAVE_OCSP */ openssl_debug_dump_ctx(ssl_ctx); return 0; } #ifdef EAP_FAST_OR_TEAP /* Pre-shared secred requires a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ #if (defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER) static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, const SSL_CIPHER **cipher, void *arg) #else /* OPENSSL_IS_BORINGSSL */ static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg) #endif /* OPENSSL_IS_BORINGSSL */ { struct tls_connection *conn = arg; int ret; #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER < 0x20700000L) if (conn == NULL || conn->session_ticket_cb == NULL) return 0; ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, s->s3->client_random, s->s3->server_random, secret); #else unsigned char client_random[SSL3_RANDOM_SIZE]; unsigned char server_random[SSL3_RANDOM_SIZE]; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; SSL_get_client_random(s, client_random, sizeof(client_random)); SSL_get_server_random(s, server_random, sizeof(server_random)); ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, client_random, server_random, secret); #endif os_free(conn->session_ticket); conn->session_ticket = NULL; if (ret <= 0) return 0; *secret_len = SSL_MAX_MASTER_KEY_LENGTH; return 1; } static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data, int len, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len); os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_memdup(data, len); if (conn->session_ticket == NULL) return 0; conn->session_ticket_len = len; return 1; } #endif /* EAP_FAST_OR_TEAP */ int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { #ifdef EAP_FAST_OR_TEAP conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; if (cb) { if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, conn) != 1) return -1; SSL_set_session_ticket_ext_cb(conn->ssl, tls_session_ticket_ext_cb, conn); } else { if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) return -1; SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL); } return 0; #else /* EAP_FAST_OR_TEAP */ return -1; #endif /* EAP_FAST_OR_TEAP */ } int tls_get_library_version(char *buf, size_t buf_len) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s", OPENSSL_VERSION_TEXT, OpenSSL_version(OPENSSL_VERSION)); #else return os_snprintf(buf, buf_len, "OpenSSL build=%s run=%s", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); #endif } void tls_connection_set_success_data(struct tls_connection *conn, struct wpabuf *data) { SSL_SESSION *sess; struct wpabuf *old; if (tls_ex_idx_session < 0) goto fail; sess = SSL_get_session(conn->ssl); if (!sess) goto fail; old = SSL_SESSION_get_ex_data(sess, tls_ex_idx_session); if (old) { wpa_printf(MSG_DEBUG, "OpenSSL: Replacing old success data %p", old); wpabuf_free(old); } if (SSL_SESSION_set_ex_data(sess, tls_ex_idx_session, data) != 1) goto fail; wpa_printf(MSG_DEBUG, "OpenSSL: Stored success data %p", data); conn->success_data = 1; return; fail: wpa_printf(MSG_INFO, "OpenSSL: Failed to store success data"); wpabuf_free(data); } void tls_connection_set_success_data_resumed(struct tls_connection *conn) { wpa_printf(MSG_DEBUG, "OpenSSL: Success data accepted for resumed session"); conn->success_data = 1; } const struct wpabuf * tls_connection_get_success_data(struct tls_connection *conn) { SSL_SESSION *sess; if (tls_ex_idx_session < 0 || !(sess = SSL_get_session(conn->ssl))) return NULL; return SSL_SESSION_get_ex_data(sess, tls_ex_idx_session); } void tls_connection_remove_session(struct tls_connection *conn) { SSL_SESSION *sess; sess = SSL_get_session(conn->ssl); if (!sess) return; if (SSL_CTX_remove_session(conn->ssl_ctx, sess) != 1) wpa_printf(MSG_DEBUG, "OpenSSL: Session was not cached"); else wpa_printf(MSG_DEBUG, "OpenSSL: Removed cached session to disable session resumption"); } int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len) { size_t len; int reused; reused = SSL_session_reused(conn->ssl); if ((conn->server && !reused) || (!conn->server && reused)) len = SSL_get_peer_finished(conn->ssl, buf, max_len); else len = SSL_get_finished(conn->ssl, buf, max_len); if (len == 0 || len > max_len) return -1; return len; } u16 tls_connection_get_cipher_suite(struct tls_connection *conn) { const SSL_CIPHER *cipher; cipher = SSL_get_current_cipher(conn->ssl); if (!cipher) return 0; #if OPENSSL_VERSION_NUMBER >= 0x10101000L && !defined(LIBRESSL_VERSION_NUMBER) return SSL_CIPHER_get_protocol_id(cipher); #else return SSL_CIPHER_get_id(cipher) & 0xFFFF; #endif } const char * tls_connection_get_peer_subject(struct tls_connection *conn) { if (conn) return conn->peer_subject; return NULL; } bool tls_connection_get_own_cert_used(struct tls_connection *conn) { if (conn) return SSL_get_certificate(conn->ssl) != NULL; return false; } diff --git a/contrib/wpa/src/eap_common/eap_pwd_common.c b/contrib/wpa/src/eap_common/eap_pwd_common.c index 2b2b8efdbd01..ff22b29b087a 100644 --- a/contrib/wpa/src/eap_common/eap_pwd_common.c +++ b/contrib/wpa/src/eap_common/eap_pwd_common.c @@ -1,449 +1,475 @@ /* * EAP server/peer: EAP-pwd shared routines * Copyright (c) 2010, Dan Harkins * * This software may be distributed under the terms of the BSD license. * See README for more details. */ #include "includes.h" #include "common.h" #include "utils/const_time.h" #include "common/dragonfly.h" #include "crypto/sha256.h" #include "crypto/crypto.h" #include "eap_defs.h" #include "eap_pwd_common.h" #define MAX_ECC_PRIME_LEN 66 /* The random function H(x) = HMAC-SHA256(0^32, x) */ struct crypto_hash * eap_pwd_h_init(void) { u8 allzero[SHA256_MAC_LEN]; os_memset(allzero, 0, SHA256_MAC_LEN); return crypto_hash_init(CRYPTO_HASH_ALG_HMAC_SHA256, allzero, SHA256_MAC_LEN); } void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len) { crypto_hash_update(hash, data, len); } void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest) { size_t len = SHA256_MAC_LEN; crypto_hash_finish(hash, digest, &len); } /* a counter-based KDF based on NIST SP800-108 */ static int eap_pwd_kdf(const u8 *key, size_t keylen, const u8 *label, size_t labellen, u8 *result, size_t resultbitlen) { struct crypto_hash *hash; u8 digest[SHA256_MAC_LEN]; u16 i, ctr, L; size_t resultbytelen, len = 0, mdlen; resultbytelen = (resultbitlen + 7) / 8; ctr = 0; L = htons(resultbitlen); while (len < resultbytelen) { ctr++; i = htons(ctr); hash = crypto_hash_init(CRYPTO_HASH_ALG_HMAC_SHA256, key, keylen); if (hash == NULL) return -1; if (ctr > 1) crypto_hash_update(hash, digest, SHA256_MAC_LEN); crypto_hash_update(hash, (u8 *) &i, sizeof(u16)); crypto_hash_update(hash, label, labellen); crypto_hash_update(hash, (u8 *) &L, sizeof(u16)); mdlen = SHA256_MAC_LEN; if (crypto_hash_finish(hash, digest, &mdlen) < 0) return -1; if ((len + mdlen) > resultbytelen) os_memcpy(result + len, digest, resultbytelen - len); else os_memcpy(result + len, digest, mdlen); len += mdlen; } /* since we're expanding to a bit length, mask off the excess */ if (resultbitlen % 8) { u8 mask = 0xff; mask <<= (8 - (resultbitlen % 8)); result[resultbytelen - 1] &= mask; } return 0; } EAP_PWD_group * get_eap_pwd_group(u16 num) { EAP_PWD_group *grp; if (!dragonfly_suitable_group(num, 1)) { wpa_printf(MSG_INFO, "EAP-pwd: unsuitable group %u", num); return NULL; } grp = os_zalloc(sizeof(EAP_PWD_group)); if (!grp) return NULL; grp->group = crypto_ec_init(num); if (!grp->group) { wpa_printf(MSG_INFO, "EAP-pwd: unable to create EC group"); os_free(grp); return NULL; } grp->group_num = num; wpa_printf(MSG_INFO, "EAP-pwd: provisioned group %d", num); return grp; } /* * compute a "random" secret point on an elliptic curve based * on the password and identities. */ int compute_password_element(EAP_PWD_group *grp, u16 num, const u8 *password, size_t password_len, const u8 *id_server, size_t id_server_len, const u8 *id_peer, size_t id_peer_len, const u8 *token) { struct crypto_bignum *qr = NULL, *qnr = NULL; u8 qr_bin[MAX_ECC_PRIME_LEN]; u8 qnr_bin[MAX_ECC_PRIME_LEN]; u8 qr_or_qnr_bin[MAX_ECC_PRIME_LEN]; u8 x_bin[MAX_ECC_PRIME_LEN]; u8 prime_bin[MAX_ECC_PRIME_LEN]; - struct crypto_bignum *tmp2 = NULL; + u8 x_y[2 * MAX_ECC_PRIME_LEN]; + struct crypto_bignum *tmp2 = NULL, *y = NULL; struct crypto_hash *hash; unsigned char pwe_digest[SHA256_MAC_LEN], *prfbuf = NULL, ctr; int ret = 0, res; u8 found = 0; /* 0 (false) or 0xff (true) to be used as const_time_* * mask */ size_t primebytelen = 0, primebitlen; struct crypto_bignum *x_candidate = NULL; const struct crypto_bignum *prime; u8 found_ctr = 0, is_odd = 0; int cmp_prime; unsigned int in_range; + unsigned int is_eq; if (grp->pwe) return -1; os_memset(x_bin, 0, sizeof(x_bin)); prime = crypto_ec_get_prime(grp->group); primebitlen = crypto_ec_prime_len_bits(grp->group); primebytelen = crypto_ec_prime_len(grp->group); if (crypto_bignum_to_bin(prime, prime_bin, sizeof(prime_bin), primebytelen) < 0) return -1; - grp->pwe = crypto_ec_point_init(grp->group); - if (!grp->pwe) { - wpa_printf(MSG_INFO, "EAP-pwd: unable to create bignums"); - goto fail; - } if ((prfbuf = os_malloc(primebytelen)) == NULL) { wpa_printf(MSG_INFO, "EAP-pwd: unable to malloc space for prf " "buffer"); goto fail; } /* get a random quadratic residue and nonresidue */ if (dragonfly_get_random_qr_qnr(prime, &qr, &qnr) < 0 || crypto_bignum_to_bin(qr, qr_bin, sizeof(qr_bin), primebytelen) < 0 || crypto_bignum_to_bin(qnr, qnr_bin, sizeof(qnr_bin), primebytelen) < 0) goto fail; os_memset(prfbuf, 0, primebytelen); ctr = 0; /* * Run through the hunting-and-pecking loop 40 times to mask the time * necessary to find PWE. The odds of PWE not being found in 40 loops is * roughly 1 in 1 trillion. */ while (ctr < 40) { ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ hash = eap_pwd_h_init(); if (hash == NULL) goto fail; eap_pwd_h_update(hash, token, sizeof(u32)); eap_pwd_h_update(hash, id_peer, id_peer_len); eap_pwd_h_update(hash, id_server, id_server_len); eap_pwd_h_update(hash, password, password_len); eap_pwd_h_update(hash, &ctr, sizeof(ctr)); eap_pwd_h_final(hash, pwe_digest); is_odd = const_time_select_u8( found, is_odd, pwe_digest[SHA256_MAC_LEN - 1] & 0x01); if (eap_pwd_kdf(pwe_digest, SHA256_MAC_LEN, (u8 *) "EAP-pwd Hunting And Pecking", os_strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen) < 0) goto fail; if (primebitlen % 8) buf_shift_right(prfbuf, primebytelen, 8 - primebitlen % 8); cmp_prime = const_time_memcmp(prfbuf, prime_bin, primebytelen); /* Create a const_time mask for selection based on prf result * being smaller than prime. */ in_range = const_time_fill_msb((unsigned int) cmp_prime); /* The algorithm description would skip the next steps if * cmp_prime >= 0, but go through them regardless to minimize * externally observable differences in behavior. */ crypto_bignum_deinit(x_candidate, 1); x_candidate = crypto_bignum_init_set(prfbuf, primebytelen); if (!x_candidate) { wpa_printf(MSG_INFO, "EAP-pwd: unable to create x_candidate"); goto fail; } wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: x_candidate", prfbuf, primebytelen); const_time_select_bin(found, x_bin, prfbuf, primebytelen, x_bin); /* * compute y^2 using the equation of the curve * * y^2 = x^3 + ax + b */ crypto_bignum_deinit(tmp2, 1); tmp2 = crypto_ec_point_compute_y_sqr(grp->group, x_candidate); if (!tmp2) goto fail; res = dragonfly_is_quadratic_residue_blind(grp->group, qr_bin, qnr_bin, tmp2); if (res < 0) goto fail; found_ctr = const_time_select_u8(found, found_ctr, ctr); /* found is 0 or 0xff here and res is 0 or 1. Bitwise OR of them * (with res converted to 0/0xff and masked with prf being below * prime) handles this in constant time. */ found |= (res & in_range) * 0xff; } if (found == 0) { wpa_printf(MSG_INFO, "EAP-pwd: unable to find random point on curve for group %d, something's fishy", num); goto fail; } /* * We know x_candidate is a quadratic residue so set it here. */ crypto_bignum_deinit(x_candidate, 1); x_candidate = crypto_bignum_init_set(x_bin, primebytelen); - if (!x_candidate || - crypto_ec_point_solve_y_coord(grp->group, grp->pwe, x_candidate, - is_odd) != 0) { - wpa_printf(MSG_INFO, "EAP-pwd: Could not solve for y"); + if (!x_candidate) + goto fail; + + /* y = sqrt(x^3 + ax + b) mod p + * if LSB(y) == LSB(pwd-seed): PWE = (x, y) + * else: PWE = (x, p - y) + * + * Calculate y and the two possible values for PWE and after that, + * use constant time selection to copy the correct alternative. + */ + y = crypto_ec_point_compute_y_sqr(grp->group, x_candidate); + if (!y || + dragonfly_sqrt(grp->group, y, y) < 0 || + crypto_bignum_to_bin(y, x_y, MAX_ECC_PRIME_LEN, primebytelen) < 0 || + crypto_bignum_sub(prime, y, y) < 0 || + crypto_bignum_to_bin(y, x_y + MAX_ECC_PRIME_LEN, + MAX_ECC_PRIME_LEN, primebytelen) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not solve y"); + goto fail; + } + + /* Constant time selection of the y coordinate from the two + * options */ + is_eq = const_time_eq(is_odd, x_y[primebytelen - 1] & 0x01); + const_time_select_bin(is_eq, x_y, x_y + MAX_ECC_PRIME_LEN, + primebytelen, x_y + primebytelen); + os_memcpy(x_y, x_bin, primebytelen); + wpa_hexdump_key(MSG_DEBUG, "EAP-pwd: PWE", x_y, 2 * primebytelen); + grp->pwe = crypto_ec_point_from_bin(grp->group, x_y); + if (!grp->pwe) { + wpa_printf(MSG_DEBUG, "EAP-pwd: Could not generate PWE"); goto fail; } /* * If there's a solution to the equation then the point must be on the * curve so why check again explicitly? OpenSSL code says this is * required by X9.62. We're not X9.62 but it can't hurt just to be sure. */ if (!crypto_ec_point_is_on_curve(grp->group, grp->pwe)) { wpa_printf(MSG_INFO, "EAP-pwd: point is not on curve"); goto fail; } wpa_printf(MSG_DEBUG, "EAP-pwd: found a PWE in %02d tries", found_ctr); if (0) { fail: crypto_ec_point_deinit(grp->pwe, 1); grp->pwe = NULL; ret = 1; } /* cleanliness and order.... */ crypto_bignum_deinit(x_candidate, 1); crypto_bignum_deinit(tmp2, 1); + crypto_bignum_deinit(y, 1); crypto_bignum_deinit(qr, 1); crypto_bignum_deinit(qnr, 1); bin_clear_free(prfbuf, primebytelen); os_memset(qr_bin, 0, sizeof(qr_bin)); os_memset(qnr_bin, 0, sizeof(qnr_bin)); os_memset(qr_or_qnr_bin, 0, sizeof(qr_or_qnr_bin)); os_memset(pwe_digest, 0, sizeof(pwe_digest)); + forced_memzero(x_y, sizeof(x_y)); return ret; } int compute_keys(EAP_PWD_group *grp, const struct crypto_bignum *k, const struct crypto_bignum *peer_scalar, const struct crypto_bignum *server_scalar, const u8 *confirm_peer, const u8 *confirm_server, const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id) { struct crypto_hash *hash; u8 mk[SHA256_MAC_LEN], *cruft; u8 msk_emsk[EAP_MSK_LEN + EAP_EMSK_LEN]; size_t prime_len, order_len; prime_len = crypto_ec_prime_len(grp->group); order_len = crypto_ec_order_len(grp->group); cruft = os_malloc(prime_len); if (!cruft) return -1; /* * first compute the session-id = TypeCode | H(ciphersuite | scal_p | * scal_s) */ session_id[0] = EAP_TYPE_PWD; hash = eap_pwd_h_init(); if (hash == NULL) { os_free(cruft); return -1; } eap_pwd_h_update(hash, (const u8 *) ciphersuite, sizeof(u32)); crypto_bignum_to_bin(peer_scalar, cruft, order_len, order_len); eap_pwd_h_update(hash, cruft, order_len); crypto_bignum_to_bin(server_scalar, cruft, order_len, order_len); eap_pwd_h_update(hash, cruft, order_len); eap_pwd_h_final(hash, &session_id[1]); /* then compute MK = H(k | confirm-peer | confirm-server) */ hash = eap_pwd_h_init(); if (hash == NULL) { os_free(cruft); return -1; } crypto_bignum_to_bin(k, cruft, prime_len, prime_len); eap_pwd_h_update(hash, cruft, prime_len); os_free(cruft); eap_pwd_h_update(hash, confirm_peer, SHA256_MAC_LEN); eap_pwd_h_update(hash, confirm_server, SHA256_MAC_LEN); eap_pwd_h_final(hash, mk); /* stretch the mk with the session-id to get MSK | EMSK */ if (eap_pwd_kdf(mk, SHA256_MAC_LEN, session_id, SHA256_MAC_LEN + 1, msk_emsk, (EAP_MSK_LEN + EAP_EMSK_LEN) * 8) < 0) { return -1; } os_memcpy(msk, msk_emsk, EAP_MSK_LEN); os_memcpy(emsk, msk_emsk + EAP_MSK_LEN, EAP_EMSK_LEN); return 1; } static int eap_pwd_element_coord_ok(const struct crypto_bignum *prime, const u8 *buf, size_t len) { struct crypto_bignum *val; int ok = 1; val = crypto_bignum_init_set(buf, len); if (!val || crypto_bignum_is_zero(val) || crypto_bignum_cmp(val, prime) >= 0) ok = 0; crypto_bignum_deinit(val, 0); return ok; } struct crypto_ec_point * eap_pwd_get_element(EAP_PWD_group *group, const u8 *buf) { struct crypto_ec_point *element; const struct crypto_bignum *prime; size_t prime_len; prime = crypto_ec_get_prime(group->group); prime_len = crypto_ec_prime_len(group->group); /* RFC 5931, 2.8.5.2.2: 0 < x,y < p */ if (!eap_pwd_element_coord_ok(prime, buf, prime_len) || !eap_pwd_element_coord_ok(prime, buf + prime_len, prime_len)) { wpa_printf(MSG_INFO, "EAP-pwd: Invalid coordinate in element"); return NULL; } element = crypto_ec_point_from_bin(group->group, buf); if (!element) { wpa_printf(MSG_INFO, "EAP-pwd: EC point from element failed"); return NULL; } /* RFC 5931, 2.8.5.2.2: on curve and not the point at infinity */ if (!crypto_ec_point_is_on_curve(group->group, element) || crypto_ec_point_is_at_infinity(group->group, element)) { wpa_printf(MSG_INFO, "EAP-pwd: Invalid element"); goto fail; } out: return element; fail: crypto_ec_point_deinit(element, 0); element = NULL; goto out; } struct crypto_bignum * eap_pwd_get_scalar(EAP_PWD_group *group, const u8 *buf) { struct crypto_bignum *scalar; const struct crypto_bignum *order; size_t order_len; order = crypto_ec_get_order(group->group); order_len = crypto_ec_order_len(group->group); /* RFC 5931, 2.8.5.2: 1 < scalar < r */ scalar = crypto_bignum_init_set(buf, order_len); if (!scalar || crypto_bignum_is_zero(scalar) || crypto_bignum_is_one(scalar) || crypto_bignum_cmp(scalar, order) >= 0) { wpa_printf(MSG_INFO, "EAP-pwd: received scalar is invalid"); crypto_bignum_deinit(scalar, 0); scalar = NULL; } return scalar; } int eap_pwd_get_rand_mask(EAP_PWD_group *group, struct crypto_bignum *_rand, struct crypto_bignum *_mask, struct crypto_bignum *scalar) { return dragonfly_generate_scalar(crypto_ec_get_order(group->group), _rand, _mask, scalar); } diff --git a/contrib/wpa/wpa_supplicant/ChangeLog b/contrib/wpa/wpa_supplicant/ChangeLog index 5ca82457ad1b..efcc6cd9c9ba 100644 --- a/contrib/wpa/wpa_supplicant/ChangeLog +++ b/contrib/wpa/wpa_supplicant/ChangeLog @@ -1,2447 +1,2500 @@ ChangeLog for wpa_supplicant +2022-01-16 - v2.10 + * SAE changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + - added support for the hash-to-element mechanism (sae_pwe=1 or + sae_pwe=2); this is currently disabled by default, but will likely + get enabled by default in the future + - fixed PMKSA caching with OKC + - added support for SAE-PK + * EAP-pwd changes + - improved protection against side channel attacks + [https://w1.fi/security/2022-1/] + * fixed P2P provision discovery processing of a specially constructed + invalid frame + [https://w1.fi/security/2021-1/] + * fixed P2P group information processing of a specially constructed + invalid frame + [https://w1.fi/security/2020-2/] + * fixed PMF disconnection protection bypass in AP mode + [https://w1.fi/security/2019-7/] + * added support for using OpenSSL 3.0 + * increased the maximum number of EAP message exchanges (mainly to + support cases with very large certificates) + * fixed various issues in experimental support for EAP-TEAP peer + * added support for DPP release 2 (Wi-Fi Device Provisioning Protocol) + * a number of MKA/MACsec fixes and extensions + * added support for SAE (WPA3-Personal) AP mode configuration + * added P2P support for EDMG (IEEE 802.11ay) channels + * fixed EAP-FAST peer with TLS GCM/CCM ciphers + * improved throughput estimation and BSS selection + * dropped support for libnl 1.1 + * added support for nl80211 control port for EAPOL frame TX/RX + * fixed OWE key derivation with groups 20 and 21; this breaks backwards + compatibility for these groups while the default group 19 remains + backwards compatible + * added support for Beacon protection + * added support for Extended Key ID for pairwise keys + * removed WEP support from the default build (CONFIG_WEP=y can be used + to enable it, if really needed) + * added a build option to remove TKIP support (CONFIG_NO_TKIP=y) + * added support for Transition Disable mechanism to allow the AP to + automatically disable transition mode to improve security + * extended D-Bus interface + * added support for PASN + * added a file-based backend for external password storage to allow + secret information to be moved away from the main configuration file + without requiring external tools + * added EAP-TLS peer support for TLS 1.3 (disabled by default for now) + * added support for SCS, MSCS, DSCP policy + * changed driver interface selection to default to automatic fallback + to other compiled in options + * a large number of other fixes, cleanup, and extensions + 2019-08-07 - v2.9 * SAE changes - disable use of groups using Brainpool curves - improved protection against side channel attacks [https://w1.fi/security/2019-6/] * EAP-pwd changes - disable use of groups using Brainpool curves - allow the set of groups to be configured (eap_pwd_groups) - improved protection against side channel attacks [https://w1.fi/security/2019-6/] * fixed FT-EAP initial mobility domain association using PMKSA caching (disabled by default for backwards compatibility; can be enabled with ft_eap_pmksa_caching=1) * fixed a regression in OpenSSL 1.1+ engine loading * added validation of RSNE in (Re)Association Response frames * fixed DPP bootstrapping URI parser of channel list * extended EAP-SIM/AKA fast re-authentication to allow use with FILS * extended ca_cert_blob to support PEM format * improved robustness of P2P Action frame scheduling * added support for EAP-SIM/AKA using anonymous@realm identity * fixed Hotspot 2.0 credential selection based on roaming consortium to ignore credentials without a specific EAP method * added experimental support for EAP-TEAP peer (RFC 7170) * added experimental support for EAP-TLS peer with TLS v1.3 * fixed a regression in WMM parameter configuration for a TDLS peer * fixed a regression in operation with drivers that offload 802.1X 4-way handshake * fixed an ECDH operation corner case with OpenSSL 2019-04-21 - v2.8 * SAE changes - added support for SAE Password Identifier - changed default configuration to enable only groups 19, 20, 21 (i.e., disable groups 25 and 26) and disable all unsuitable groups completely based on REVmd changes - do not regenerate PWE unnecessarily when the AP uses the anti-clogging token mechanisms - fixed some association cases where both SAE and FT-SAE were enabled on both the station and the selected AP - started to prefer FT-SAE over SAE AKM if both are enabled - started to prefer FT-SAE over FT-PSK if both are enabled - fixed FT-SAE when SAE PMKSA caching is used - reject use of unsuitable groups based on new implementation guidance in REVmd (allow only FFC groups with prime >= 3072 bits and ECC groups with prime >= 256) - minimize timing and memory use differences in PWE derivation [https://w1.fi/security/2019-1/] (CVE-2019-9494) * EAP-pwd changes - minimize timing and memory use differences in PWE derivation [https://w1.fi/security/2019-2/] (CVE-2019-9495) - verify server scalar/element [https://w1.fi/security/2019-4/] (CVE-2019-9499) - fix message reassembly issue with unexpected fragment [https://w1.fi/security/2019-5/] - enforce rand,mask generation rules more strictly - fix a memory leak in PWE derivation - disallow ECC groups with a prime under 256 bits (groups 25, 26, and 27) * fixed CONFIG_IEEE80211R=y (FT) build without CONFIG_FILS=y * Hotspot 2.0 changes - do not indicate release number that is higher than the one AP supports - added support for release number 3 - enable PMF automatically for network profiles created from credentials * fixed OWE network profile saving * fixed DPP network profile saving * added support for RSN operating channel validation (CONFIG_OCV=y and network profile parameter ocv=1) * added Multi-AP backhaul STA support * fixed build with LibreSSL * number of MKA/MACsec fixes and extensions * extended domain_match and domain_suffix_match to allow list of values * fixed dNSName matching in domain_match and domain_suffix_match when using wolfSSL * started to prefer FT-EAP-SHA384 over WPA-EAP-SUITE-B-192 AKM if both are enabled * extended nl80211 Connect and external authentication to support SAE, FT-SAE, FT-EAP-SHA384 * fixed KEK2 derivation for FILS+FT * extended client_cert file to allow loading of a chain of PEM encoded certificates * extended beacon reporting functionality * extended D-Bus interface with number of new properties * fixed a regression in FT-over-DS with mac80211-based drivers * OpenSSL: allow systemwide policies to be overridden * extended driver flags indication for separate 802.1X and PSK 4-way handshake offload capability * added support for random P2P Device/Interface Address use * extended PEAP to derive EMSK to enable use with ERP/FILS * extended WPS to allow SAE configuration to be added automatically for PSK (wps_cred_add_sae=1) * removed support for the old D-Bus interface (CONFIG_CTRL_IFACE_DBUS) * extended domain_match and domain_suffix_match to allow list of values * added a RSN workaround for misbehaving PMF APs that advertise IGTK/BIP KeyID using incorrect byte order * fixed PTK rekeying with FILS and FT 2018-12-02 - v2.7 * fixed WPA packet number reuse with replayed messages and key reinstallation [https://w1.fi/security/2017-1/] (CVE-2017-13077, CVE-2017-13078, CVE-2017-13079, CVE-2017-13080, CVE-2017-13081, CVE-2017-13082, CVE-2017-13086, CVE-2017-13087, CVE-2017-13088) * fixed unauthenticated EAPOL-Key decryption in wpa_supplicant [https://w1.fi/security/2018-1/] (CVE-2018-14526) * added support for FILS (IEEE 802.11ai) shared key authentication * added support for OWE (Opportunistic Wireless Encryption, RFC 8110; and transition mode defined by WFA) * added support for DPP (Wi-Fi Device Provisioning Protocol) * added support for RSA 3k key case with Suite B 192-bit level * fixed Suite B PMKSA caching not to update PMKID during each 4-way handshake * fixed EAP-pwd pre-processing with PasswordHashHash * added EAP-pwd client support for salted passwords * fixed a regression in TDLS prohibited bit validation * started to use estimated throughput to avoid undesired signal strength based roaming decision * MACsec/MKA: - new macsec_linux driver interface support for the Linux kernel macsec module - number of fixes and extensions * added support for external persistent storage of PMKSA cache (PMKSA_GET/PMKSA_ADD control interface commands; and MESH_PMKSA_GET/MESH_PMKSA_SET for the mesh case) * fixed mesh channel configuration pri/sec switch case * added support for beacon report * large number of other fixes, cleanup, and extensions * added support for randomizing local address for GAS queries (gas_rand_mac_addr parameter) * fixed EAP-SIM/AKA/AKA' ext auth cases within TLS tunnel * added option for using random WPS UUID (auto_uuid=1) * added SHA256-hash support for OCSP certificate matching * fixed EAP-AKA' to add AT_KDF into Synchronization-Failure * fixed a regression in RSN pre-authentication candidate selection * added option to configure allowed group management cipher suites (group_mgmt network profile parameter) * removed all PeerKey functionality * fixed nl80211 AP and mesh mode configuration regression with Linux 4.15 and newer * added ap_isolate configuration option for AP mode * added support for nl80211 to offload 4-way handshake into the driver * added support for using wolfSSL cryptographic library * SAE - added support for configuring SAE password separately of the WPA2 PSK/passphrase - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection for SAE; note: this is not backwards compatible, i.e., both the AP and station side implementations will need to be update at the same time to maintain interoperability - added support for Password Identifier - fixed FT-SAE PMKID matching * Hotspot 2.0 - added support for fetching of Operator Icon Metadata ANQP-element - added support for Roaming Consortium Selection element - added support for Terms and Conditions - added support for OSEN connection in a shared RSN BSS - added support for fetching Venue URL information * added support for using OpenSSL 1.1.1 * FT - disabled PMKSA caching with FT since it is not fully functional - added support for SHA384 based AKM - added support for BIP ciphers BIP-CMAC-256, BIP-GMAC-128, BIP-GMAC-256 in addition to previously supported BIP-CMAC-128 - fixed additional IE inclusion in Reassociation Request frame when using FT protocol 2016-10-02 - v2.6 * fixed WNM Sleep Mode processing when PMF is not enabled [http://w1.fi/security/2015-6/] (CVE-2015-5310) * fixed EAP-pwd last fragment validation [http://w1.fi/security/2015-7/] (CVE-2015-5315) * fixed EAP-pwd unexpected Confirm message processing [http://w1.fi/security/2015-8/] (CVE-2015-5316) * fixed WPS configuration update vulnerability with malformed passphrase [http://w1.fi/security/2016-1/] (CVE-2016-4476) * fixed configuration update vulnerability with malformed parameters set over the local control interface [http://w1.fi/security/2016-1/] (CVE-2016-4477) * fixed TK configuration to the driver in EAPOL-Key 3/4 retry case * extended channel switch support for P2P GO * started to throttle control interface event message bursts to avoid issues with monitor sockets running out of buffer space * mesh mode fixes/improvements - generate proper AID for peer - enable WMM by default - add VHT support - fix PMKID derivation - improve robustness on various exchanges - fix peer link counting in reconnect case - improve mesh joining behavior - allow DTIM period to be configured - allow HT to be disabled (disable_ht=1) - add MESH_PEER_ADD and MESH_PEER_REMOVE commands - add support for PMKSA caching - add minimal support for SAE group negotiation - allow pairwise/group cipher to be configured in the network profile - use ieee80211w profile parameter to enable/disable PMF and derive a separate TX IGTK if PMF is enabled instead of using MGTK incorrectly - fix AEK and MTK derivation - remove GTKdata and IGTKdata from Mesh Peering Confirm/Close - note: these changes are not fully backwards compatible for secure (RSN) mesh network * fixed PMKID derivation with SAE * added support for requesting and fetching arbitrary ANQP-elements without internal support in wpa_supplicant for the specific element (anqp[265]= in "BSS " command output) * P2P - filter control characters in group client device names to be consistent with other P2P peer cases - support VHT 80+80 MHz and 160 MHz - indicate group completion in P2P Client role after data association instead of already after the WPS provisioning step - improve group-join operation to use SSID, if known, to filter BSS entries - added optional ssid= argument to P2P_CONNECT for join case - added P2P_GROUP_MEMBER command to fetch client interface address * P2PS - fix follow-on PD Response behavior - fix PD Response generation for unknown peer - fix persistent group reporting - add channel policy to PD Request - add group SSID to the P2PS-PROV-DONE event - allow "P2P_CONNECT p2ps" to be used without specifying the default PIN * BoringSSL - support for OCSP stapling - support building of h20-osu-client * D-Bus - add ExpectDisconnect() - add global config parameters as properties - add SaveConfig() - add VendorElemAdd(), VendorElemGet(), VendorElemRem() * fixed Suite B 192-bit AKM to use proper PMK length (note: this makes old releases incompatible with the fixed behavior) * improved PMF behavior for cases where the AP and STA has different configuration by not trying to connect in some corner cases where the connection cannot succeed * added option to reopen debug log (e.g., to rotate the file) upon receipt of SIGHUP signal * EAP-pwd: added support for Brainpool Elliptic Curves (with OpenSSL 1.0.2 and newer) * fixed EAPOL reauthentication after FT protocol run * fixed FTIE generation for 4-way handshake after FT protocol run * extended INTERFACE_ADD command to allow certain type (sta/ap) interface to be created * fixed and improved various FST operations * added 80+80 MHz and 160 MHz VHT support for IBSS/mesh * fixed SIGNAL_POLL in IBSS and mesh cases * added an option to abort an ongoing scan (used to speed up connection and can also be done with the new ABORT_SCAN command) * TLS client - do not verify CA certificates when ca_cert is not specified - support validating server certificate hash - support SHA384 and SHA512 hashes - add signature_algorithms extension into ClientHello - support TLS v1.2 signature algorithm with SHA384 and SHA512 - support server certificate probing - allow specific TLS versions to be disabled with phase2 parameter - support extKeyUsage - support PKCS #5 v2.0 PBES2 - support PKCS #5 with PKCS #12 style key decryption - minimal support for PKCS #12 - support OCSP stapling (including ocsp_multi) * OpenSSL - support OpenSSL 1.1 API changes - drop support for OpenSSL 0.9.8 - drop support for OpenSSL 1.0.0 * added support for multiple schedule scan plans (sched_scan_plans) * added support for external server certificate chain validation (tls_ext_cert_check=1 in the network profile phase1 parameter) * made phase2 parser more strict about correct use of auth= and autheap= values * improved GAS offchannel operations with comeback request * added SIGNAL_MONITOR command to request signal strength monitoring events * added command for retrieving HS 2.0 icons with in-memory storage (REQ_HS20_ICON, GET_HS20_ICON, DEL_HS20_ICON commands and RX-HS20-ICON event) * enabled ACS support for AP mode operations with wpa_supplicant * EAP-PEAP: fixed interoperability issue with Windows 2012r2 server ("Invalid Compound_MAC in cryptobinding TLV") * EAP-TTLS: fixed success after fragmented final Phase 2 message * VHT: added interoperability workaround for 80+80 and 160 MHz channels * WNM: workaround for broken AP operating class behavior * added kqueue(2) support for eloop (CONFIG_ELOOP_KQUEUE) * nl80211: - add support for full station state operations - do not add NL80211_ATTR_SMPS_MODE attribute if HT is disabled - add NL80211_ATTR_PREV_BSSID with Connect command - fix IEEE 802.1X/WEP EAP reauthentication and rekeying to use unencrypted EAPOL frames * added initial MBO support; number of extensions to WNM BSS Transition Management * added support for PBSS/PCP and P2P on 60 GHz * Interworking: add credential realm to EAP-TLS identity * fixed EAPOL-Key Request Secure bit to be 1 if PTK is set * HS 2.0: add support for configuring frame filters * added POLL_STA command to check connectivity in AP mode * added initial functionality for location related operations * started to ignore pmf=1/2 parameter for non-RSN networks * added wps_disabled=1 network profile parameter to allow AP mode to be started without enabling WPS * wpa_cli: added action script support for AP-ENABLED and AP-DISABLED events * improved Public Action frame addressing - add gas_address3 configuration parameter to control Address 3 behavior * number of small fixes 2015-09-27 - v2.5 * fixed P2P validation of SSID element length before copying it [http://w1.fi/security/2015-1/] (CVE-2015-1863) * fixed WPS UPnP vulnerability with HTTP chunked transfer encoding [http://w1.fi/security/2015-2/] (CVE-2015-4141) * fixed WMM Action frame parser (AP mode) [http://w1.fi/security/2015-3/] (CVE-2015-4142) * fixed EAP-pwd peer missing payload length validation [http://w1.fi/security/2015-4/] (CVE-2015-4143, CVE-2015-4144, CVE-2015-4145, CVE-2015-4146) * fixed validation of WPS and P2P NFC NDEF record payload length [http://w1.fi/security/2015-5/] * nl80211: - added VHT configuration for IBSS - fixed vendor command handling to check OUI properly - allow driver-based roaming to change ESS * added AVG_BEACON_RSSI to SIGNAL_POLL output * wpa_cli: added tab completion for number of commands * removed unmaintained and not yet completed SChannel/CryptoAPI support * modified Extended Capabilities element use in Probe Request frames to include all cases if any of the values are non-zero * added support for dynamically creating/removing a virtual interface with interface_add/interface_remove * added support for hashed password (NtHash) in EAP-pwd peer * added support for memory-only PSK/passphrase (mem_only_psk=1 and CTRL-REQ/RSP-PSK_PASSPHRASE) * P2P - optimize scan frequencies list when re-joining a persistent group - fixed number of sequences with nl80211 P2P Device interface - added operating class 125 for P2P use cases (this allows 5 GHz channels 161 and 169 to be used if they are enabled in the current regulatory domain) - number of fixes to P2PS functionality - do not allow 40 MHz co-ex PRI/SEC switch to force MCC - extended support for preferred channel listing * D-Bus: - fixed WPS property of fi.w1.wpa_supplicant1.BSS interface - fixed PresenceRequest to use group interface - added new signals: FindStopped, WPS pbc-overlap, GroupFormationFailure, WPS timeout, InvitationReceived - added new methods: WPS Cancel, P2P Cancel, Reconnect, RemoveClient - added manufacturer info * added EAP-EKE peer support for deriving Session-Id * added wps_priority configuration parameter to set the default priority for all network profiles added by WPS * added support to request a scan with specific SSIDs with the SCAN command (optional "ssid " arguments) * removed support for WEP40/WEP104 as a group cipher with WPA/WPA2 * fixed SAE group selection in an error case * modified SAE routines to be more robust and PWE generation to be stronger against timing attacks * added support for Brainpool Elliptic Curves with SAE * added support for CCMP-256 and GCMP-256 as group ciphers with FT * fixed BSS selection based on estimated throughput * added option to disable TLSv1.0 with OpenSSL (phase1="tls_disable_tlsv1_0=1") * added Fast Session Transfer (FST) module * fixed OpenSSL PKCS#12 extra certificate handling * fixed key derivation for Suite B 192-bit AKM (this breaks compatibility with the earlier version) * added RSN IE to Mesh Peering Open/Confirm frames * number of small fixes 2015-03-15 - v2.4 * allow OpenSSL cipher configuration to be set for internal EAP server (openssl_ciphers parameter) * fixed number of small issues based on hwsim test case failures and static analyzer reports * P2P: - add new=<0/1> flag to P2P-DEVICE-FOUND events - add passive channels in invitation response from P2P Client - enable nl80211 P2P_DEVICE support by default - fix regresssion in disallow_freq preventing search on social channels - fix regressions in P2P SD query processing - try to re-invite with social operating channel if no common channels in invitation - allow cross connection on parent interface (this fixes number of use cases with nl80211) - add support for P2P services (P2PS) - add p2p_go_ctwindow configuration parameter to allow GO CTWindow to be configured * increase postponing of EAPOL-Start by one second with AP/GO that supports WPS 2.0 (this makes it less likely to trigger extra roundtrip of identity frames) * add support for PMKSA caching with SAE * add support for control mesh BSS (IEEE 802.11s) operations * fixed number of issues with D-Bus P2P commands * fixed regression in ap_scan=2 special case for WPS * fixed macsec_validate configuration * add a workaround for incorrectly behaving APs that try to use EAPOL-Key descriptor version 3 when the station supports PMF even if PMF is not enabled on the AP * allow TLS v1.1 and v1.2 to be negotiated by default; previous behavior of disabling these can be configured to work around issues with broken servers with phase1="tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1" * add support for Suite B (128-bit and 192-bit level) key management and cipher suites * add WMM-AC support (WMM_AC_ADDTS/WMM_AC_DELTS) * improved BSS Transition Management processing * add support for neighbor report * add support for link measurement * fixed expiration of BSS entry with all-zeros BSSID * add optional LAST_ID=x argument to LIST_NETWORK to allow all configured networks to be listed even with huge number of network profiles * add support for EAP Re-Authentication Protocol (ERP) * fixed EAP-IKEv2 fragmentation reassembly * improved PKCS#11 configuration for OpenSSL * set stdout to be line-buffered * add TDLS channel switch configuration * add support for MAC address randomization in scans with nl80211 * enable HT for IBSS if supported by the driver * add BSSID black and white lists (bssid_blacklist, bssid_whitelist) * add support for domain_suffix_match with GnuTLS * add OCSP stapling client support with GnuTLS * include peer certificate in EAP events even without a separate probe operation; old behavior can be restored with cert_in_cb=0 * add peer ceritficate alt subject name to EAP events (CTRL-EVENT-EAP-PEER-ALT) * add domain_match network profile parameter (similar to domain_suffix_match, but full match is required) * enable AP/GO mode HT Tx STBC automatically based on driver support * add ANQP-QUERY-DONE event to provide information on ANQP parsing status * allow passive scanning to be forced with passive_scan=1 * add a workaround for Linux packet socket behavior when interface is in bridge * increase 5 GHz band preference in BSS selection (estimate SNR, if info not available from driver; estimate maximum throughput based on common HT/VHT/specific TX rate support) * add INTERWORKING_ADD_NETWORK ctrl_iface command; this can be used to implement Interworking network selection behavior in upper layers software components * add optional reassoc_same_bss_optim=1 (disabled by default) optimization to avoid unnecessary Authentication frame exchange * extend TDLS frame padding workaround to cover all packets * allow wpa_supplicant to recover nl80211 functionality if the cfg80211 module gets removed and reloaded without restarting wpa_supplicant * allow hostapd DFS implementation to be used in wpa_supplicant AP mode 2014-10-09 - v2.3 * fixed number of minor issues identified in static analyzer warnings * fixed wfd_dev_info to be more careful and not read beyond the buffer when parsing invalid information for P2P-DEVICE-FOUND * extended P2P and GAS query operations to support drivers that have maximum remain-on-channel time below 1000 ms (500 ms is the current minimum supported value) * added p2p_search_delay parameter to make the default p2p_find delay configurable * improved P2P operating channel selection for various multi-channel concurrency cases * fixed some TDLS failure cases to clean up driver state * fixed dynamic interface addition cases with nl80211 to avoid adding ifindex values to incorrect interface to skip foreign interface events properly * added TDLS workaround for some APs that may add extra data to the end of a short frame * fixed EAP-AKA' message parser with multiple AT_KDF attributes * added configuration option (p2p_passphrase_len) to allow longer passphrases to be generated for P2P groups * fixed IBSS channel configuration in some corner cases * improved HT/VHT/QoS parameter setup for TDLS * modified D-Bus interface for P2P peers/groups * started to use constant time comparison for various password and hash values to reduce possibility of any externally measurable timing differences * extended explicit clearing of freed memory and expired keys to avoid keeping private data in memory longer than necessary * added optional scan_id parameter to the SCAN command to allow manual scan requests for active scans for specific configured SSIDs * fixed CTRL-EVENT-REGDOM-CHANGE event init parameter value * added option to set Hotspot 2.0 Rel 2 update_identifier in network configuration to support external configuration * modified Android PNO functionality to send Probe Request frames only for hidden SSIDs (based on scan_ssid=1) * added generic mechanism for adding vendor elements into frames at runtime (VENDOR_ELEM_ADD, VENDOR_ELEM_GET, VENDOR_ELEM_REMOVE) * added fields to show unrecognized vendor elements in P2P_PEER * removed EAP-TTLS/MSCHAPv2 interoperability workaround so that MS-CHAP2-Success is required to be present regardless of eap_workaround configuration * modified EAP fast session resumption to allow results to be used only with the same network block that generated them * extended freq_list configuration to apply for sched_scan as well as normal scan * modified WPS to merge mixed-WPA/WPA2 credentials from a single session * fixed nl80211/RTM_DELLINK processing when a P2P GO interface is removed from a bridge * fixed number of small P2P issues to make negotiations more robust in corner cases * added experimental support for using temporary, random local MAC address (mac_addr and preassoc_mac_addr parameters); this is disabled by default (i.e., previous behavior of using permanent address is maintained if configuration is not changed) * added D-Bus interface for setting/clearing WFD IEs * fixed TDLS AID configuration for VHT * modified -m configuration file to be used only for the P2P non-netdev management device and do not load this for the default station interface or load the station interface configuration for the P2P management interface * fixed external MAC address changes while wpa_supplicant is running * started to enable HT (if supported by the driver) for IBSS * fixed wpa_cli action script execution to use more robust mechanism (CVE-2014-3686) 2014-06-04 - v2.2 * added DFS indicator to get_capability freq * added/fixed nl80211 functionality - BSSID/frequency hint for driver-based BSS selection - fix tearing down WDS STA interfaces - support vendor specific driver command (VENDOR []) - GO interface teardown optimization - allow beacon interval to be configured for IBSS - add SHA256-based AKM suites to CONNECT/ASSOCIATE commands * removed unused NFC_RX_HANDOVER_REQ and NFC_RX_HANDOVER_SEL control interface commands (the more generic NFC_REPORT_HANDOVER is now used) * fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding; this fixes password with include UTF-8 characters that use three-byte encoding EAP methods that use NtPasswordHash * fixed couple of sequences where radio work items could get stuck, e.g., when rfkill blocking happens during scanning or when scan-for-auth workaround is used * P2P enhancements/fixes - enable enable U-APSD on GO automatically if the driver indicates support for this - fixed some service discovery cases with broadcast queries not being sent to all stations - fixed Probe Request frame triggering invitation to trigger only a single invitation instance even if multiple Probe Request frames are received - fixed a potential NULL pointer dereference crash when processing an invalid Invitation Request frame - add optional configuration file for the P2P_DEVICE parameters - optimize scan for GO during persistent group invocation - fix possible segmentation fault when PBC overlap is detected while using a separate P2P group interface - improve GO Negotiation robustness by allowing GO Negotiation Confirmation to be retransmitted - do use freed memory on device found event when P2P NFC * added phase1 network parameter options for disabling TLS v1.1 and v1.2 to allow workarounds with misbehaving AAA servers (tls_disable_tlsv1_1=1 and tls_disable_tlsv1_2=1) * added support for OCSP stapling to validate AAA server certificate during TLS exchange * Interworking/Hotspot 2.0 enhancements - prefer the last added network in Interworking connection to make the behavior more consistent with likely user expectation - roaming partner configuration (roaming_partner within a cred block) - support Hotspot 2.0 Release 2 * "hs20_anqp_get 8" to request OSU Providers list * "hs20_icon_request " to request icon files * "fetch_osu" and "cancel_osu_fetch" to start/stop full OSU provider search (all suitable APs in scan results) * OSEN network for online signup connection * min_{dl,ul}_bandwidth_{home,roaming} cred parameters * max_bss_load cred parameter * req_conn_capab cred parameter * sp_priority cred parameter * ocsp cred parameter * slow down automatic connection attempts on EAP failure to meet required behavior (no more than 10 retries within a 10-minute interval) * sample implementation of online signup client (both SPP and OMA-DM protocols) (hs20/client/*) - fixed GAS indication for additional comeback delay with status code 95 - extend ANQP_GET to accept Hotspot 2.0 subtypes ANQP_GET [,]... [,hs20:][...,hs20:] - add control interface events CRED-ADDED , CRED-MODIFIED , CRED-REMOVED - add "GET_CRED " command - enable FT for the connection automatically if the AP advertises support for this - fix a case where auto_interworking=1 could end up stopping scanning * fixed TDLS interoperability issues with supported operating class in some deployed stations * internal TLS implementation enhancements/fixes - add SHA256-based cipher suites - add DHE-RSA cipher suites - fix X.509 validation of PKCS#1 signature to check for extra data * fixed PTK derivation for CCMP-256 and GCMP-256 * added "reattach" command for fast reassociate-back-to-same-BSS * allow PMF to be enabled for AP mode operation with the ieee80211w parameter * added "get_capability tdls" command * added option to set config blobs through control interface with "SET blob " * D-Bus interface extensions/fixes - make p2p_no_group_iface configurable - declare ServiceDiscoveryRequest method properly - export peer's device address as a property - make reassociate command behave like the control interface one, i.e., to allow connection from disconnected state * added optional "freq=" parameter to SET pno * added optional "freq=" parameter to SELECT_NETWORK * fixed OBSS scan result processing for 20/40 MHz co-ex report * remove WPS 1.0 only support, i.e., WSC 2.0 support is now enabled whenever CONFIG_WPS=y is set * fixed regression in parsing of WNM Sleep Mode exit key data * fixed potential segmentation fault and memory leaks in WNM neighbor report processing * EAP-pwd fixes - fragmentation of PWD-Confirm-Resp - fix memory leak when fragmentation is used - fix possible segmentation fault on EAP method deinit if an invalid group is negotiated * added MACsec/IEEE Std 802.1X-2010 PAE implementation (currently available only with the macsec_qca driver wrapper) * fixed EAP-SIM counter-too-small message * added 'dup_network ' command; this can be used to clone the psk field without having toextract it from wpa_supplicant * fixed GSM authentication on USIM * added support for using epoll in eloop (CONFIG_ELOOP_EPOLL=y) * fixed some concurrent virtual interface cases with dedicated P2P management interface to not catch events from removed interface (this could result in the management interface getting disabled) * fixed a memory leak in SAE random number generation * fixed off-by-one bounds checking in printf_encode() - this could result in some control interface ATTACH command cases terminating wpa_supplicant * fixed EAPOL-Key exchange when GCMP is used with SHA256-based AKM * various bug fixes 2014-02-04 - v2.1 * added support for simultaneous authentication of equals (SAE) for stronger password-based authentication with WPA2-Personal * improved P2P negotiation and group formation robustness - avoid unnecessary Dialog Token value changes during retries - avoid more concurrent scanning cases during full group formation sequence - do not use potentially obsolete scan result data from driver cache for peer discovery/updates - avoid undesired re-starting of GO negotiation based on Probe Request frames - increase GO Negotiation and Invitation timeouts to address busy environments and peers that take long time to react to messages, e.g., due to power saving - P2P Device interface type * improved P2P channel selection (use more peer information and allow more local options) * added support for optional per-device PSK assignment by P2P GO (wpa_cli p2p_set per_sta_psk <0/1>) * added P2P_REMOVE_CLIENT for removing a client from P2P groups (including persistent groups); this can be used to securely remove a client from a group if per-device PSKs are used * added more configuration flexibility for allowed P2P GO/client channels (p2p_no_go_freq list and p2p_add_cli_chan=0/1) * added nl80211 functionality - VHT configuration for nl80211 - MFP (IEEE 802.11w) information for nl80211 command API - support split wiphy dump - FT (IEEE 802.11r) with driver-based SME - use advertised number of supported concurrent channels - QoS Mapping configuration * improved TDLS negotiation robustness * added more TDLS peer parameters to be configured to the driver * optimized connection time by allowing recently received scan results to be used instead of having to run through a new scan * fixed ctrl_iface BSS command iteration with RANGE argument and no exact matches; also fixed argument parsing for some cases with multiple arguments * added 'SCAN TYPE=ONLY' ctrl_iface command to request manual scan without executing roaming/network re-selection on scan results * added Session-Id derivation for EAP peer methods * added fully automated regression testing with mac80211_hwsim * changed configuration parser to reject invalid integer values * allow AP/Enrollee to be specified with BSSID instead of UUID for WPS ER operations * disable network block temporarily on repeated connection failures * changed the default driver interface from wext to nl80211 if both are included in the build * remove duplicate networks if WPS provisioning is run multiple times * remove duplicate networks when Interworking network selection uses the same network * added global freq_list configuration to allow scan frequencies to be limited for all cases instead of just for a specific network block * added support for BSS Transition Management * added option to use "IFNAME= " prefix to use the global control interface connection to perform per-interface commands; similarly, allow global control interface to be used as a monitor interface to receive events from all interfaces * fixed OKC-based PMKSA cache entry clearing * fixed TKIP group key configuration with FT * added support for using OCSP stapling to validate server certificate (ocsp=1 as optional and ocsp=2 as mandatory) * added EAP-EKE peer * added peer restart detection for IBSS RSN * added domain_suffix_match (and domain_suffix_match2 for Phase 2 EAP-TLS) to specify additional constraint for the server certificate domain name * added support for external SIM/USIM processing in EAP-SIM, EAP-AKA, and EAP-AKA' (CTRL-REQ-SIM and CTRL-RSP-SIM commands over control interface) * added global bgscan configuration option as a default for all network blocks that do not specify their own bgscan parameters * added D-Bus methods for TDLS * added more control to scan requests - "SCAN freq=" can be used to specify which channels are scanned (comma-separated frequency ranges in MHz) - "SCAN passive=1" can be used to request a passive scan (no Probe Request frames are sent) - "SCAN use_id" can be used to request a scan id to be returned and included in event messages related to this specific scan operation - "SCAN only_new=1" can be used to request the driver/cfg80211 to report only BSS entries that have been updated during this scan round - these optional arguments to the SCAN command can be combined with each other * modified behavior on externally triggered scans - avoid concurrent operations requiring full control of the radio when an externally triggered scan is detected - do not use results for internal roaming decision * added a new cred block parameter 'temporary' to allow credential blocks to be stored separately even if wpa_supplicant configuration file is used to maintain other network information * added "radio work" framework to schedule exclusive radio operations for off-channel functionality - reduce issues with concurrent operations that try to control which channel is used - allow external programs to request exclusive radio control in a way that avoids conflicts with wpa_supplicant * added support for using Protected Dual of Public Action frames for GAS/ANQP exchanges when associated with PMF * added support for WPS+NFC updates and P2P+NFC - improved protocol for WPS - P2P group formation/join based on NFC connection handover - new IPv4 address assignment for P2P groups (ip_addr_* configuration parameters on the GO) to replace DHCP - option to fetch and report alternative carrier records for external NFC operations * various bug fixes 2013-01-12 - v2.0 * removed Qt3-based wpa_gui (obsoleted by wpa_qui-qt4) * removed unmaintained driver wrappers broadcom, iphone, osx, ralink, hostap, madwifi (hostap and madwifi remain available for hostapd; their wpa_supplicant functionality is obsoleted by wext) * improved debug logging (human readable event names, interface name included in more entries) * changed AP mode behavior to enable WPS only for open and WPA/WPA2-Personal configuration * improved P2P concurrency operations - better coordination of concurrent scan and P2P search operations - avoid concurrent remain-on-channel operation requests by canceling previous operations prior to starting a new one - reject operations that would require multi-channel concurrency if the driver does not support it - add parameter to select whether STA or P2P connection is preferred if the driver cannot support both at the same time - allow driver to indicate channel changes - added optional delay= parameter for p2p_find to avoid taking all radio resources - use 500 ms p2p_find search delay by default during concurrent operations - allow all channels in GO Negotiation if the driver supports multi-channel concurrency * added number of small changes to make it easier for static analyzers to understand the implementation * fixed number of small bugs (see git logs for more details) * nl80211: number of updates to use new cfg80211/nl80211 functionality - replace monitor interface with nl80211 commands for AP mode - additional information for driver-based AP SME - STA entry authorization in RSN IBSS * EAP-pwd: - fixed KDF for group 21 and zero-padding - added support for fragmentation - increased maximum number of hunting-and-pecking iterations * avoid excessive Probe Response retries for broadcast Probe Request frames (only with drivers using wpa_supplicant AP mode SME/MLME) * added "GET country" ctrl_iface command * do not save an invalid network block in wpa_supplicant.conf to avoid problems reading the file on next start * send STA connected/disconnected ctrl_iface events to both the P2P group and parent interfaces * added preliminary support for using TLS v1.2 (CONFIG_TLSV12=y) * added "SET pno <1/0>" ctrl_iface command to start/stop preferred network offload with sched_scan driver command * merged in number of changes from Android repository for P2P, nl80211, and build parameters * changed P2P GO mode configuration to use driver capabilities to automatically enable HT operations when supported * added "wpa_cli status wps" command to fetch WPA2-Personal passhrase for WPS use cases in AP mode * EAP-AKA: keep pseudonym identity across EAP exchanges to match EAP-SIM behavior * improved reassociation behavior in cases where association is rejected or when an AP disconnects us to handle common load balancing mechanisms - try to avoid extra scans when the needed information is available * added optional "join" argument for p2p_prov_disc ctrl_iface command * added group ifname to P2P-PROV-DISC-* events * added P2P Device Address to AP-STA-DISCONNECTED event and use p2p_dev_addr parameter name with AP-STA-CONNECTED * added workarounds for WPS PBC overlap detection for some P2P use cases where deployed stations work incorrectly * optimize WPS connection speed by disconnecting prior to WPS scan and by using single channel scans when AP channel is known * PCSC and SIM/USIM improvements: - accept 0x67 (Wrong length) as a response to READ RECORD to fix issues with some USIM cards - try to read MNC length from SIM/USIM - build realm according to 3GPP TS 23.003 with identity from the SIM - allow T1 protocol to be enabled * added more WPS and P2P information available through D-Bus * improve P2P negotiation robustness - extra waits to get ACK frames through - longer timeouts for cases where deployed devices have been identified have issues meeting the specification requirements - more retries for some P2P frames - handle race conditions in GO Negotiation start by both devices - ignore unexpected GO Negotiation Response frame * added support for libnl 3.2 and newer * added P2P persistent group info to P2P_PEER data * maintain a list of P2P Clients for persistent group on GO * AP: increased initial group key handshake retransmit timeout to 500 ms * added optional dev_id parameter for p2p_find * added P2P-FIND-STOPPED ctrl_iface event * fixed issues in WPA/RSN element validation when roaming with ap_scan=1 and driver-based BSS selection * do not expire P2P peer entries while connected with the peer in a group * fixed WSC element inclusion in cases where P2P is disabled * AP: added a WPS workaround for mixed mode AP Settings with Windows 7 * EAP-SIM: fixed AT_COUNTER_TOO_SMALL use * EAP-SIM/AKA: append realm to pseudonym identity * EAP-SIM/AKA: store pseudonym identity in network configuration to allow it to persist over multiple EAP sessions and wpa_supplicant restarts * EAP-AKA': updated to RFC 5448 (username prefixes changed); note: this breaks interoperability with older versions * added support for WFA Hotspot 2.0 - GAS/ANQP to fetch network information - credential configuration and automatic network selections based on credential match with ANQP information * limited PMKSA cache entries to be used only with the network context that was used to create them * improved PMKSA cache expiration to avoid unnecessary disconnections * adjusted bgscan_simple fast-scan backoff to avoid too frequent background scans * removed ctrl_iface event on P2P PD Response in join-group case * added option to fetch BSS table entry based on P2P Device Address ("BSS p2p_dev_addr=") * added BSS entry age to ctrl_iface BSS command output * added optional MASK=0xH option for ctrl_iface BSS command to select which fields are included in the response * added optional RANGE=ALL|N1-N2 option for ctrl_iface BSS command to fetch information about several BSSes in one call * simplified licensing terms by selecting the BSD license as the only alternative * added "P2P_SET disallow_freq " ctrl_iface command to disable channels from P2P use * added p2p_pref_chan configuration parameter to allow preferred P2P channels to be specified * added support for advertising immediate availability of a WPS credential for P2P use cases * optimized scan operations for P2P use cases (use single channel scan for a specific SSID when possible) * EAP-TTLS: fixed peer challenge generation for MSCHAPv2 * SME: do not use reassociation after explicit disconnection request (local or a notification from an AP) * added support for sending debug info to Linux tracing (-T on command line) * added support for using Deauthentication reason code 3 as an indication of P2P group termination * added wps_vendor_ext_m1 configuration parameter to allow vendor specific attributes to be added to WPS M1 * started using separate TLS library context for tunneled TLS (EAP-PEAP/TLS, EAP-TTLS/TLS, EAP-FAST/TLS) to support different CA certificate configuration between Phase 1 and Phase 2 * added optional "auto" parameter for p2p_connect to request automatic GO Negotiation vs. join-a-group selection * added disabled_scan_offload parameter to disable automatic scan offloading (sched_scan) * added optional persistent= parameter for p2p_connect to allow forcing of a specific SSID/passphrase for GO Negotiation * added support for OBSS scan requests and 20/40 BSS coexistence reports * reject PD Request for unknown group * removed scripts and notes related to Windows binary releases (which have not been used starting from 1.x) * added initial support for WNM operations - Keep-alive based on BSS max idle period - WNM-Sleep Mode - minimal BSS Transition Management processing * added autoscan module to control scanning behavior while not connected - autoscan_periodic and autoscan_exponential modules * added new WPS NFC ctrl_iface mechanism - added initial support NFC connection handover - removed obsoleted WPS_OOB command (including support for deprecated UFD config_method) * added optional framework for external password storage ("ext:") * wpa_cli: added optional support for controlling wpa_supplicant remotely over UDP (CONFIG_CTRL_IFACE=udp-remote) for testing purposes * wpa_cli: extended tab completion to more commands * changed SSID output to use printf-escaped strings instead of masking of non-ASCII characters - SSID can now be configured in the same format: ssid=P"abc\x00test" * removed default ACM=1 from AC_VO and AC_VI * added optional "ht40" argument for P2P ctrl_iface commands to allow 40 MHz channels to be requested on the 5 GHz band * added optional parameters for p2p_invite command to specify channel when reinvoking a persistent group as the GO * improved FIPS mode builds with OpenSSL - "make fips" with CONFIG_FIPS=y to build wpa_supplicant with the OpenSSL FIPS object module - replace low level OpenSSL AES API calls to use EVP - use OpenSSL keying material exporter when possible - do not export TLS keys in FIPS mode - remove MD5 from CONFIG_FIPS=y builds - use OpenSSL function for PKBDF2 passphrase-to-PSK - use OpenSSL HMAC implementation - mix RAND_bytes() output into random_get_bytes() to force OpenSSL DRBG to be used in FIPS mode - use OpenSSL CMAC implementation * added mechanism to disable TLS Session Ticket extension - a workaround for servers that do not support TLS extensions that was enabled by default in recent OpenSSL versions - tls_disable_session_ticket=1 - automatically disable TLS Session Ticket extension by default when using EAP-TLS/PEAP/TTLS (i.e., only use it with EAP-FAST) * changed VENDOR-TEST EAP method to use proper private enterprise number (this will not interoperate with older versions) * disable network block temporarily on authentication failures * improved WPS AP selection during WPS PIN iteration * added support for configuring GCMP cipher for IEEE 802.11ad * added support for Wi-Fi Display extensions - WFD_SUBELEMENT_SET ctrl_iface command to configure WFD subelements - SET wifi_display <0/1> to disable/enable WFD support - WFD service discovery - an external program is needed to manage the audio/video streaming and codecs * optimized scan result use for network selection - use the internal BSS table instead of raw scan results - allow unnecessary scans to be skipped if fresh information is available (e.g., after GAS/ANQP round for Interworking) * added support for 256-bit AES with internal TLS implementation * allow peer to propose channel in P2P invitation process for a persistent group * added disallow_aps parameter to allow BSSIDs/SSIDs to be disallowed from network selection * re-enable the networks disabled during WPS operations * allow P2P functionality to be disabled per interface (p2p_disabled=1) * added secondary device types into P2P_PEER output * added an option to disable use of a separate P2P group interface (p2p_no_group_iface=1) * fixed P2P Bonjour SD to match entries with both compressed and not compressed domain name format and support multiple Bonjour PTR matches for the same key * use deauthentication instead of disassociation for all disconnection operations; this removes the now unused disassociate() wpa_driver_ops callback * optimized PSK generation on P2P GO by caching results to avoid multiple PBKDF2 operations * added okc=1 global configuration parameter to allow OKC to be enabled by default for all network blocks * added a workaround for WPS PBC session overlap detection to avoid interop issues with deployed station implementations that do not remove active PBC indication from Probe Request frames properly * added basic support for 60 GHz band * extend EAPOL frames processing workaround for roaming cases (postpone processing of unexpected EAPOL frame until association event to handle reordered events) 2012-05-10 - v1.0 * bsd: Add support for setting HT values in IFM_MMASK. * Delay STA entry removal until Deauth/Disassoc TX status in AP mode. This allows the driver to use PS buffering of Deauthentication and Disassociation frames when the STA is in power save sleep. Only available with drivers that provide TX status events for Deauth/ Disassoc frames (nl80211). * Drop oldest unknown BSS table entries first. This makes it less likely to hit connection issues in environments with huge number of visible APs. * Add systemd support. * Add support for setting the syslog facility from the config file at build time. * atheros: Add support for IEEE 802.11w configuration. * AP mode: Allow enable HT20 if driver supports it, by setting the config parameter ieee80211n. * Allow AP mode to disconnect STAs based on low ACK condition (when the data connection is not working properly, e.g., due to the STA going outside the range of the AP). Disabled by default, enable by config option disassoc_low_ack. * nl80211: - Support GTK rekey offload. - Support PMKSA candidate events. This adds support for RSN pre-authentication with nl80211 interface and drivers that handle roaming internally. * dbus: - Add a DBus signal for EAP SM requests, emitted on the Interface object. - Export max scan ssids supported by the driver as MaxScanSSID. - Add signal Certification for information about server certification. - Add BSSExpireAge and BSSExpireCount interface properties and support set/get, which allows for setting BSS cache expiration age and expiration scan count. - Add ConfigFile to AddInterface properties. - Add Interface.Country property and support to get/set the value. - Add DBus property CurrentAuthMode. - P2P DBus API added. - Emit property changed events (for property BSSs) when adding/ removing BSSs. - Treat '' in SSIDs of Interface.Scan as a request for broadcast scan, instead of ignoring it. - Add DBus getter/setter for FastReauth. - Raise PropertiesChanged on org.freedesktop.DBus.Properties. * wpa_cli: - Send AP-STA-DISCONNECTED event when an AP disconnects a station due to inactivity. - Make second argument to set command optional. This can be used to indicate a zero length value. - Add signal_poll command. - Add bss_expire_age and bss_expire_count commands to set/get BSS cache expiration age and expiration scan count. - Add ability to set scan interval (the time in seconds wpa_s waits before requesting a new scan after failing to find a suitable network in scan results) using scan_interval command. - Add event CTRL-EVENT-ASSOC-REJECT for association rejected. - Add command get version, that returns wpa_supplicant version string. - Add command sta_autoconnect for disabling automatic reconnection on receiving disconnection event. - Setting bssid parameter to an empty string "" or any can now be used to clear the bssid_set flag in a network block, i.e., to remove bssid filtering. - Add tdls_testing command to add a special testing feature for changing TDLS behavior. Build param CONFIG_TDLS_TESTING must be enabled as well. - For interworking, add wpa_cli commands interworking_select, interworking_connect, anqp_get, fetch_anqp, and stop_fetch_anqp. - Many P2P commands were added. See README-P2P. - Many WPS/WPS ER commands - see WPS/WPS ER sections for details. - Allow set command to change global config parameters. - Add log_level command, which can be used to display the current debugging level and to change the log level during run time. - Add note command, which can be used to insert notes to the debug log. - Add internal line edit implementation. CONFIG_WPA_CLI_EDIT=y can now be used to build wpa_cli with internal implementation of line editing and history support. This can be used as a replacement for CONFIG_READLINE=y. * AP mode: Add max_num_sta config option, which can be used to limit the number of stations allowed to connect to the AP. * Add WPA_IGNORE_CONFIG_ERRORS build option to continue in case of bad config file. * wext: Increase scan timeout from 5 to 10 seconds. * Add blacklist command, allowing an external program to manage the BSS blacklist and display its current contents. * WPS: - Add wpa_cli wps_pin get command for generating random PINs. This can be used in a UI to generate a PIN without starting WPS (or P2P) operation. - Set RF bands based on driver capabilities, instead of hardcoding them. - Add mechanism for indicating non-standard WPS errors. - Add CONFIG_WPS_REG_DISABLE_OPEN=y option to disable open networks by default. - Add wps_ap_pin cli command for wpa_supplicant AP mode. - Add wps_check_pin cli command for processing PIN from user input. UIs can use this command to process a PIN entered by a user and to validate the checksum digit (if present). - Cancel WPS operation on PBC session overlap detection. - New wps_cancel command in wpa_cli will cancel a pending WPS operation. - wpa_cli action: Add WPS_EVENT_SUCCESS and WPS_EVENT_FAIL handlers. - Trigger WPS config update on Manufacturer, Model Name, Model Number, and Serial Number changes. - Fragment size is now configurable for EAP-WSC peer. Use wpa_cli set wps_fragment_size . - Disable AP PIN after 10 consecutive failures. Slow down attacks on failures up to 10. - Allow AP to start in Enrollee mode without AP PIN for probing, to be compatible with Windows 7. - Add Config Error into WPS-FAIL events to provide more info to the user on how to resolve the issue. - Label and Display config methods are not allowed to be enabled at the same time, since it is unclear which PIN to use if both methods are advertised. - When controlling multiple interfaces: - apply WPS commands to all interfaces configured to use WPS - apply WPS config changes to all interfaces that use WPS - when an attack is detected on any interface, disable AP PIN on all interfaces * WPS ER: - Add special AP Setup Locked mode to allow read only ER. ap_setup_locked=2 can now be used to enable a special mode where WPS ER can learn the current AP settings, but cannot change them. - Show SetSelectedRegistrar events as ctrl_iface events - Add wps_er_set_config to enroll a network based on a local network configuration block instead of having to (re-)learn the current AP settings with wps_er_learn. - Allow AP filtering based on IP address, add ctrl_iface event for learned AP settings, add wps_er_config command to configure an AP. * WPS 2.0: Add support for WPS 2.0 (CONFIG_WPS2) - Add build option CONFIG_WPS_EXTENSIBILITY_TESTING to enable tool for testing protocol extensibility. - Add build option CONFIG_WPS_STRICT to allow disabling of WPS workarounds. - Add support for AuthorizedMACs attribute. * TDLS: - Propagate TDLS related nl80211 capability flags from kernel and add them as driver capability flags. If the driver doesn't support capabilities, assume TDLS is supported internally. When TDLS is explicitly not supported, disable all user facing TDLS operations. - Allow TDLS to be disabled at runtime (mostly for testing). Use set tdls_disabled. - Honor AP TDLS settings that prohibit/allow TDLS. - Add a special testing feature for changing TDLS behavior. Use CONFIG_TDLS_TESTING build param to enable. Configure at runtime with tdls_testing cli command. - Add support for TDLS 802.11z. * wlantest: Add a tool wlantest for IEEE802.11 protocol testing. wlantest can be used to capture frames from a monitor interface for realtime capturing or from pcap files for offline analysis. * Interworking: Support added for 802.11u. Enable in .config with CONFIG_INTERWORKING. See wpa_supplicant.conf for config parameters for interworking. wpa_cli commands added to support this are interworking_select, interworking_connect, anqp_get, fetch_anqp, and stop_fetch_anqp. * Android: Add build and runtime support for Android wpa_supplicant. * bgscan learn: Add new bgscan that learns BSS information based on previous scans, and uses that information to dynamically generate the list of channels for background scans. * Add a new debug message level for excessive information. Use -ddd to enable. * TLS: Add support for tls_disable_time_checks=1 in client mode. * Internal TLS: - Add support for TLS v1.1 (RFC 4346). Enable with build parameter CONFIG_TLSV11. - Add domainComponent parser for X.509 names. * Linux: Add RFKill support by adding an interface state "disabled". * Reorder some IEs to get closer to IEEE 802.11 standard. Move WMM into end of Beacon, Probe Resp and (Re)Assoc Resp frames. Move HT IEs to be later in (Re)Assoc Resp. * Solaris: Add support for wired 802.1X client. * Wi-Fi Direct support. See README-P2P for more information. * Many bugfixes. 2010-04-18 - v0.7.2 * nl80211: fixed number of issues with roaming * avoid unnecessary roaming if multiple APs with similar signal strength are present in scan results * add TLS client events and server probing to ease design of automatic detection of EAP parameters * add option for server certificate matching (SHA256 hash of the certificate) instead of trusted CA certificate configuration * bsd: Cleaned up driver wrapper and added various low-level configuration options * wpa_gui-qt4: do not show too frequent WPS AP available events as tray messages * TNC: fixed issues with fragmentation * EAP-TNC: add Flags field into fragment acknowledgement (needed to interoperate with other implementations; may potentially breaks compatibility with older wpa_supplicant/hostapd versions) * wpa_cli: added option for using a separate process to receive event messages to reduce latency in showing these (CFLAGS += -DCONFIG_WPA_CLI_FORK=y in .config to enable this) * maximum BSS table size can now be configured (bss_max_count) * BSSes to be included in the BSS table can be filtered based on configured SSIDs to save memory (filter_ssids) * fix number of issues with IEEE 802.11r/FT; this version is not backwards compatible with old versions * nl80211: add support for IEEE 802.11r/FT protocol (both over-the-air and over-the-DS) * add freq_list network configuration parameter to allow the AP selection to filter out entries based on the operating channel * add signal strength change events for bgscan; this allows more dynamic changes to background scanning interval based on changes in the signal strength with the current AP; this improves roaming within ESS quite a bit, e.g., with bgscan="simple:30:-45:300" in the network configuration block to request background scans less frequently when signal strength remains good and to automatically trigger background scans whenever signal strength drops noticeably (this is currently only available with nl80211) * add BSSID and reason code (if available) to disconnect event messages * wpa_gui-qt4: more complete support for translating the GUI with linguist and add German translation * fix DH padding with internal crypto code (mainly, for WPS) * do not trigger initial scan automatically anymore if there are no enabled networks 2010-01-16 - v0.7.1 * cleaned up driver wrapper API (struct wpa_driver_ops); the new API is not fully backwards compatible, so out-of-tree driver wrappers will need modifications * cleaned up various module interfaces * merge hostapd and wpa_supplicant developers' documentation into a single document * nl80211: use explicit deauthentication to clear cfg80211 state to avoid issues when roaming between APs * dbus: major design changes in the new D-Bus API (fi.w1.wpa_supplicant1) * nl80211: added support for IBSS networks * added internal debugging mechanism with backtrace support and memory allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) * added WPS ER unsubscription command to more cleanly unregister from receiving UPnP events when ER is terminated * cleaned up AP mode operations to avoid need for virtual driver_ops wrapper * added BSS table to maintain more complete scan result information over multiple scans (that may include only partial results) * wpa_gui-qt4: update Peers dialog information more dynamically while the dialog is kept open * fixed PKCS#12 use with OpenSSL 1.0.0 * driver_wext: Added cfg80211-specific optimization to avoid some unnecessary scans and to speed up association 2009-11-21 - v0.7.0 * increased wpa_cli ping interval to 5 seconds and made this configurable with a new command line options (-G) * fixed scan buffer processing with WEXT to handle up to 65535 byte result buffer (previously, limited to 32768 bytes) * allow multiple driver wrappers to be specified on command line (e.g., -Dnl80211,wext); the first one that is able to initialize the interface will be used * added support for multiple SSIDs per scan request to optimize scan_ssid=1 operations in ap_scan=1 mode (i.e., search for hidden SSIDs); this requires driver support and can currently be used only with nl80211 * added support for WPS USBA out-of-band mechanism with USB Flash Drives (UFD) (CONFIG_WPS_UFD=y) * driver_ndis: add PAE group address to the multicast address list to fix wired IEEE 802.1X authentication * fixed IEEE 802.11r key derivation function to match with the standard (note: this breaks interoperability with previous version) [Bug 303] * added better support for drivers that allow separate authentication and association commands (e.g., mac80211-based Linux drivers with nl80211; SME in wpa_supplicant); this allows over-the-air FT protocol to be used (IEEE 802.11r) * fixed SHA-256 based key derivation function to match with the standard when using CCMP (for IEEE 802.11r and IEEE 802.11w) (note: this breaks interoperability with previous version) [Bug 307] * use shared driver wrapper files with hostapd * added AP mode functionality (CONFIG_AP=y) with mode=2 in the network block; this can be used for open and WPA2-Personal networks (optionally, with WPS); this links in parts of hostapd functionality into wpa_supplicant * wpa_gui-qt4: added new Peers dialog to show information about peers (other devices, including APs and stations, etc. in the neighborhood) * added support for WPS External Registrar functionality (configure APs and enroll new devices); can be used with wpa_gui-qt4 Peers dialog and wpa_cli commands wps_er_start, wps_er_stop, wps_er_pin, wps_er_pbc, wps_er_learn (this can also be used with a new 'none' driver wrapper if no wireless device or IEEE 802.1X on wired is needed) * driver_nl80211: multiple updates to provide support for new Linux nl80211/mac80211 functionality * updated management frame protection to use IEEE Std 802.11w-2009 * fixed number of small WPS issues and added workarounds to interoperate with common deployed broken implementations * added support for NFC out-of-band mechanism with WPS * driver_ndis: fixed wired IEEE 802.1X authentication with PAE group address frames * added preliminary support for IEEE 802.11r RIC processing * added support for specifying subset of enabled frequencies to scan (scan_freq option in the network configuration block); this can speed up scanning process considerably if it is known that only a small subset of channels is actually used in the network (this is currently supported only with -Dnl80211) * added a workaround for race condition between receiving the association event and the following EAPOL-Key * added background scan and roaming infrastructure to allow network-specific optimizations to be used to improve roaming within an ESS (same SSID) * added new DBus interface (fi.w1.wpa_supplicant1) 2009-01-06 - v0.6.7 * added support for Wi-Fi Protected Setup (WPS) (wpa_supplicant can now be configured to act as a WPS Enrollee to enroll credentials for a network using PIN and PBC methods; in addition, wpa_supplicant can act as a wireless WPS Registrar to configure an AP); WPS support can be enabled by adding CONFIG_WPS=y into .config and setting the runtime configuration variables in wpa_supplicant.conf (see WPS section in the example configuration file); new wpa_cli commands wps_pin, wps_pbc, and wps_reg are used to manage WPS negotiation; see README-WPS for more details * added support for EAP-AKA' (draft-arkko-eap-aka-kdf) * added support for using driver_test over UDP socket * fixed PEAPv0 Cryptobinding interoperability issue with Windows Server 2008 NPS; optional cryptobinding is now enabled (again) by default * fixed PSK editing in wpa_gui * changed EAP-GPSK to use the IANA assigned EAP method type 51 * added a Windows installer that includes WinPcap and all the needed DLLs; in addition, it set up the registry automatically so that user will only need start wpa_gui to get prompted to start the wpasvc servide and add a new interface if needed through wpa_gui dialog * updated management frame protection to use IEEE 802.11w/D7.0 2008-11-23 - v0.6.6 * added Milenage SIM/USIM emulator for EAP-SIM/EAP-AKA (can be used to simulate test SIM/USIM card with a known private key; enable with CONFIG_SIM_SIMULATOR=y/CONFIG_USIM_SIMULATOR=y in .config and password="Ki:OPc"/password="Ki:OPc:SQN" in network configuration) * added a new network configuration option, wpa_ptk_rekey, that can be used to enforce frequent PTK rekeying, e.g., to mitigate some attacks against TKIP deficiencies * added an optional mitigation mechanism for certain attacks against TKIP by delaying Michael MIC error reports by a random amount of time between 0 and 60 seconds; this can be enabled with a build option CONFIG_DELAYED_MIC_ERROR_REPORT=y in .config * fixed EAP-AKA to use RES Length field in AT_RES as length in bits, not bytes * updated OpenSSL code for EAP-FAST to use an updated version of the session ticket overriding API that was included into the upstream OpenSSL 0.9.9 tree on 2008-11-15 (no additional OpenSSL patch is needed with that version anymore) * updated userspace MLME instructions to match with the current Linux mac80211 implementation; please also note that this can only be used with driver_nl80211.c (the old code from driver_wext.c was removed) * added support (Linux only) for RoboSwitch chipsets (often found in consumer grade routers); driver interface 'roboswitch' * fixed canceling of PMKSA caching when using drivers that generate RSN IE and refuse to drop PMKIDs that wpa_supplicant does not know about 2008-11-01 - v0.6.5 * added support for SHA-256 as X.509 certificate digest when using the internal X.509/TLSv1 implementation * updated management frame protection to use IEEE 802.11w/D6.0 * added support for using SHA256-based stronger key derivation for WPA2 (IEEE 802.11w) * fixed FT (IEEE 802.11r) authentication after a failed association to use correct FTIE * added support for configuring Phase 2 (inner/tunneled) authentication method with wpa_gui-qt4 2008-08-10 - v0.6.4 * added support for EAP Sequences in EAP-FAST Phase 2 * added support for using TNC with EAP-FAST * added driver_ps3 for the PS3 Linux wireless driver * added support for optional cryptobinding with PEAPv0 * fixed the OpenSSL patches (0.9.8g and 0.9.9) for EAP-FAST to allow fallback to full handshake if server rejects PAC-Opaque * added fragmentation support for EAP-TNC * added support for parsing PKCS #8 formatted private keys into the internal TLS implementation (both PKCS #1 RSA key and PKCS #8 encapsulated RSA key can now be used) * added option of using faster, but larger, routines in the internal LibTomMath (for internal TLS implementation) to speed up DH and RSA calculations (CONFIG_INTERNAL_LIBTOMMATH_FAST=y) * fixed race condition between disassociation event and group key handshake to avoid getting stuck in incorrect state [Bug 261] * fixed opportunistic key caching (proactive_key_caching) 2008-02-22 - v0.6.3 * removed 'nai' and 'eappsk' network configuration variables that were previously used for configuring user identity and key for EAP-PSK, EAP-PAX, EAP-SAKE, and EAP-GPSK. 'identity' field is now used as the replacement for 'nai' (if old configuration used a separate 'identity' value, that would now be configured as 'anonymous_identity'). 'password' field is now used as the replacement for 'eappsk' (it can also be set using hexstring to present random binary data) * removed '-w' command line parameter (wait for interface to be added, if needed); cleaner way of handling this functionality is to use an external mechanism (e.g., hotplug scripts) that start wpa_supplicant when an interface is added * updated FT support to use the latest draft, IEEE 802.11r/D9.0 * added ctrl_iface monitor event (CTRL-EVENT-SCAN-RESULTS) for indicating when new scan results become available * added new ctrl_iface command, BSS, to allow scan results to be fetched without hitting the message size limits (this command can be used to iterate through the scan results one BSS at the time) * fixed EAP-SIM not to include AT_NONCE_MT and AT_SELECTED_VERSION attributes in EAP-SIM Start/Response when using fast reauthentication * fixed EAPOL not to end up in infinite loop when processing dynamic WEP keys with IEEE 802.1X * fixed problems in getting NDIS events from WMI on Windows 2000 2008-01-01 - v0.6.2 * added support for Makefile builds to include debug-log-to-a-file functionality (CONFIG_DEBUG_FILE=y and -f on command line) * fixed EAP-SIM and EAP-AKA message parser to validate attribute lengths properly to avoid potential crash caused by invalid messages * added data structure for storing allocated buffers (struct wpabuf); this does not affect wpa_supplicant usage, but many of the APIs changed and various interfaces (e.g., EAP) is not compatible with old versions * added support for protecting EAP-AKA/Identity messages with AT_CHECKCODE (optional feature in RFC 4187) * added support for protected result indication with AT_RESULT_IND for EAP-SIM and EAP-AKA (phase1="result_ind=1") * added driver_wext workaround for race condition between scanning and association with drivers that take very long time to scan all channels (e.g., madwifi with dual-band cards); wpa_supplicant is now using a longer hardcoded timeout for the scan if the driver supports notifications for scan completion (SIOCGIWSCAN event); this helps, e.g., in cases where wpa_supplicant and madwifi driver ended up in loop where the driver did not even try to associate * stop EAPOL timer tick when no timers are in use in order to reduce power consumption (no need to wake up the process once per second) [Bug 237] * added support for privilege separation (run only minimal part of wpa_supplicant functionality as root and rest as unprivileged, non-root process); see 'Privilege separation' in README for details; this is disabled by default and can be enabled with CONFIG_PRIVSEP=y in .config * changed scan results data structure to include all information elements to make it easier to support new IEs; old get_scan_result() driver_ops is still supported for backwards compatibility (results are converted internally to the new format), but all drivers should start using the new get_scan_results2() to make them more likely to work with new features * Qt4 version of wpa_gui (wpa_gui-qt4 subdirectory) is now native Qt4 application, i.e., it does not require Qt3Support anymore; Windows binary of wpa_gui.exe is now from this directory and only requires QtCore4.dll and QtGui4.dll libraries * updated Windows binary build to use Qt 4.3.3 and made Qt DLLs available as a separate package to make wpa_gui installation easier: http://w1.fi/wpa_supplicant/qt4/wpa_gui-qt433-windows-dll.zip * added support for EAP-IKEv2 (draft-tschofenig-eap-ikev2-15.txt); only shared key/password authentication is supported in this version 2007-11-24 - v0.6.1 * added support for configuring password as NtPasswordHash (16-byte MD4 hash of password) in hash:<32 hex digits> format * added support for fallback from abbreviated TLS handshake to full handshake when using EAP-FAST (e.g., due to an expired PAC-Opaque) * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest draft (draft-ietf-emu-eap-gpsk-07.txt) * added support for drivers that take care of RSN 4-way handshake internally (WPA_DRIVER_FLAGS_4WAY_HANDSHAKE in get_capa flags and WPA_ALG_PMK in set_key) * added an experimental port for Mac OS X (CONFIG_DRIVER_OSX=y in .config); this version supports only ap_scan=2 mode and allow the driver to take care of the 4-way handshake * fixed a buffer overflow in parsing TSF from scan results when using driver_wext.c with a driver that includes the TSF (e.g., iwl4965) [Bug 232] * updated FT support to use the latest draft, IEEE 802.11r/D8.0 * fixed an integer overflow issue in the ASN.1 parser used by the (experimental) internal TLS implementation to avoid a potential buffer read overflow * fixed a race condition with -W option (wait for a control interface monitor before starting) that could have caused the first messages to be lost * added support for processing TNCC-TNCS-Messages to report recommendation (allow/none/isolate) when using TNC [Bug 243] 2007-05-28 - v0.6.0 * added network configuration parameter 'frequency' for setting initial channel for IBSS (adhoc) networks * added experimental IEEE 802.11r/D6.0 support * updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48 * updated EAP-PSK to use the IANA-allocated EAP type 47 * fixed EAP-PAX key derivation * fixed EAP-PSK bit ordering of the Flags field * fixed EAP-PEAP/TTLS/FAST to use the correct EAP identifier in tunnelled identity request (previously, the identifier from the outer method was used, not the tunnelled identifier which could be different) * added support for fragmentation of outer TLS packets during Phase 2 of EAP-PEAP/TTLS/FAST * fixed EAP-TTLS AVP parser processing for too short AVP lengths * added support for EAP-FAST authentication with inner methods that generate MSK (e.g., EAP-MSCHAPv2 that was previously only supported for PAC provisioning) * added support for authenticated EAP-FAST provisioning * added support for configuring maximum number of EAP-FAST PACs to store in a PAC list (fast_max_pac_list_len= in phase1 string) * added support for storing EAP-FAST PACs in binary format (fast_pac_format=binary in phase1 string) * fixed dbus ctrl_iface to validate message interface before dispatching to avoid a possible segfault [Bug 190] * fixed PeerKey key derivation to use the correct PRF label * updated Windows binary build to link against OpenSSL 0.9.8d and added support for EAP-FAST * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest draft (draft-ietf-emu-eap-gpsk-04.txt) * fixed EAP-AKA Notification processing to allow Notification to be processed after AKA Challenge response has been sent * updated to use IEEE 802.11w/D2.0 for management frame protection (still experimental) * fixed EAP-TTLS implementation not to crash on use of freed memory if TLS library initialization fails * added support for EAP-TNC (Trusted Network Connect) (this version implements the EAP-TNC method and EAP-TTLS changes needed to run two methods in sequence (IF-T) and the IF-IMC and IF-TNCCS interfaces from TNCC) 2006-11-24 - v0.5.6 * added experimental, integrated TLSv1 client implementation with the needed X.509/ASN.1/RSA/bignum processing (this can be enabled by setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in .config); this can be useful, e.g., if the target system does not have a suitable TLS library and a minimal code size is required (total size of this internal TLS/crypto code is bit under 50 kB on x86 and the crypto code is shared by rest of the supplicant so some of it was already required; TLSv1/X.509/ASN.1/RSA added about 25 kB) * removed STAKey handshake since PeerKey handshake has replaced it in IEEE 802.11ma and there are no known deployments of STAKey * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest draft (draft-ietf-emu-eap-gpsk-01.txt) * added preliminary implementation of IEEE 802.11w/D1.0 (management frame protection) (Note: this requires driver support to work properly.) (Note2: IEEE 802.11w is an unapproved draft and subject to change.) * fixed Windows named pipes ctrl_iface to not stop listening for commands if client program opens a named pipe and closes it immediately without sending a command * fixed USIM PIN status determination for the case that PIN is not needed (this allows EAP-AKA to be used with USIM cards that do not use PIN) * added support for reading 3G USIM AID from EF_DIR to allow EAP-AKA to be used with cards that do not support file selection based on partial AID * added support for matching the subjectAltName of the authentication server certificate against multiple name components (e.g., altsubject_match="DNS:server.example.com;DNS:server2.example.com") * fixed EAP-SIM/AKA key derivation for re-authentication case (only affects IEEE 802.1X with dynamic WEP keys) * changed ctrl_iface network configuration 'get' operations to not return password/key material; if these fields are requested, "*" will be returned if the password/key is set, but the value of the parameter is not exposed 2006-08-27 - v0.5.5 * added support for building Windows version with UNICODE defined (wide-char functions) * driver_ndis: fixed static WEP configuration to avoid race condition issues with some NDIS drivers between association and setting WEP keys * driver_ndis: added validation for IELength value in scan results to avoid crashes when using buggy NDIS drivers [Bug 165] * fixed Release|Win32 target in the Visual Studio project files (previously, only Debug|Win32 target was set properly) * changed control interface API call wpa_ctrl_pending() to allow it to return -1 on error (e.g., connection lost); control interface clients will need to make sure that they verify that the value is indeed >0 when determining whether there are pending messages * added an alternative control interface backend for Windows targets: Named Pipe (CONFIG_CTRL_IFACE=named_pipe); this is now the default control interface mechanism for Windows builds (previously, UDP to localhost was used) * changed ctrl_interface configuration for UNIX domain sockets: - deprecated ctrl_interface_group variable (it may be removed in future versions) - allow both directory and group be configured with ctrl_interface in following format: DIR=/var/run/wpa_supplicant GROUP=wheel - ctrl_interface=/var/run/wpa_supplicant is still supported for the case when group is not changed * added support for controlling more than one interface per process in Windows version * added a workaround for a case where the AP is using unknown address (e.g., MAC address of the wired interface) as the source address for EAPOL-Key frames; previously, that source address was used as the destination for EAPOL-Key frames and in key derivation; now, BSSID is used even if the source address does not match with it (this resolves an interoperability issue with Thomson SpeedTouch 580) * added a workaround for UDP-based control interface (which was used in Windows builds before this release) to prevent packets with forged addresses from being accepted as local control requests * removed ndis_events.cpp and possibility of using external ndis_events.exe; C version (ndis_events.c) is fully functional and there is no desire to maintain two separate versions of this implementation * ndis_events: Changed NDIS event notification design to use WMI to learn the adapter description through Win32_PnPEntity class; this should fix some cases where the adapter name was not recognized correctly (e.g., with some USB WLAN adapters, e.g., Ralink RT2500 USB) [Bug 113] * fixed selection of the first network in ap_scan=2 mode; previously, wpa_supplicant could get stuck in SCANNING state when only the first network for enabled (e.g., after 'wpa_cli select_network 0') * winsvc: added support for configuring ctrl_interface parameters in registry (ctrl_interface string value in HKLM\SOFTWARE\wpa_supplicant\interfaces\0000 key); this new value is required to enable control interface (previously, this was hardcoded to be enabled) * allow wpa_gui subdirectory to be built with both Qt3 and Qt4 * converted wpa_gui-qt4 subdirectory to use Qt4 specific project format 2006-06-20 - v0.5.4 * fixed build with CONFIG_STAKEY=y [Bug 143] * added support for doing MLME (IEEE 802.11 management frame processing) in wpa_supplicant when using Devicescape IEEE 802.11 stack (wireless-dev.git tree) * added a new network block configuration option, fragment_size, to configure the maximum EAP fragment size * driver_ndis: Disable WZC automatically for the selected interface to avoid conflicts with two programs trying to control the radio; WZC will be re-enabled (if it was enabled originally) when wpa_supplicant is terminated * added an experimental TLSv1 client implementation (CONFIG_TLS=internal) that can be used instead of an external TLS library, e.g., to reduce total size requirement on systems that do not include any TLS library by default (this is not yet complete; basic functionality is there, but certificate validation is not yet included) * added PeerKey handshake implementation for IEEE 802.11e direct link setup (DLS) to replace STAKey handshake * fixed WPA PSK update through ctrl_iface for the case where the old PSK was derived from an ASCII passphrase and the new PSK is set as a raw PSK (hex string) * added new configuration option for identifying which network block was used (id_str in wpa_supplicant.conf; included on WPA_EVENT_CONNECT monitor event and as WPA_ID_STR environmental variable in wpa_cli action scripts; in addition WPA_ID variable is set to the current unique identifier that wpa_supplicant assigned automatically for the network and that can be used with GET_NETWORK/SET_NETWORK ctrl_iface commands) * wpa_cli action script is now called only when the connect/disconnect status changes or when associating with a different network * fixed configuration parser not to remove CCMP from group cipher list if WPA-None (adhoc) is used (pairwise=NONE in that case) * fixed integrated NDIS events processing not to hang the process due to a missed change in eloop_win.c API in v0.5.3 [Bug 155] * added support for EAP Generalized Pre-Shared Key (EAP-GPSK, draft-clancy-emu-eap-shared-secret-00.txt) * added Microsoft Visual Studio 2005 solution and project files for build wpa_supplicant for Windows (see vs2005 subdirectory) * eloop_win: fixed unregistration of Windows events * l2_packet_winpcap: fixed a deadlock in deinitializing l2_packet at the end of RSN pre-authentication and added unregistration of a Windows event to avoid getting eloop_win stuck with an invalid handle * driver_ndis: added support for selecting AP based on BSSID * added new environmental variable for wpa_cli action scripts: WPA_CTRL_DIR is the current control interface directory * driver_ndis: added support for using NDISUIO instead of WinPcap for OID set/query operations (CONFIG_USE_NDISUIO=y in .config); with new l2_packet_ndis (CONFIG_L2_PACKET=ndis), this can be used to build wpa_supplicant without requiring WinPcap; note that using NDISUIO requires that WZC is disabled (net stop wzcsvc) since NDISUIO allows only one application to open the device * changed NDIS driver naming to only include device GUID, e.g., {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D}, instead of including WinPcap specific \Device\NPF_ prefix before the GUID; the prefix is still allowed for backwards compatibility, but it is not required anymore when specifying the interface * driver_ndis: re-initialize driver interface is the adapter is removed and re-inserted [Bug 159] * driver_madwifi: fixed TKIP and CCMP sequence number configuration on big endian hosts [Bug 146] 2006-04-27 - v0.5.3 * fixed EAP-GTC response to include correct user identity when run as phase 2 method of EAP-FAST (i.e., EAP-FAST did not work in v0.5.2) * driver_ndis: Fixed encryption mode configuration for unencrypted networks (some NDIS drivers ignored this, but others, e.g., Broadcom, refused to associate with open networks) [Bug 106] * driver_ndis: use BSSID OID polling to detect when IBSS network is formed even when ndis_events code is included since some NDIS drivers do not generate media connect events in IBSS mode * config_winreg: allow global ctrl_interface parameter to be configured in Windows registry * config_winreg: added support for saving configuration data into Windows registry * added support for controlling network device operational state (dormant/up) for Linux 2.6.17 to improve DHCP processing (see http://www.flamewarmaster.de/software/dhcpclient/ for a DHCP client that can use this information) * driver_wext: added support for WE-21 change to SSID configuration * driver_wext: fixed privacy configuration for static WEP keys mode [Bug 140] * added an optional driver_ops callback for MLME-SETPROTECTION.request primitive * added support for EAP-SAKE (no EAP method number allocated yet, so this is using the same experimental type 255 as EAP-PSK) * added support for dynamically loading EAP methods (.so files) instead of requiring them to be statically linked in; this is disabled by default (see CONFIG_DYNAMIC_EAP_METHODS in defconfig for information on how to use this) 2006-03-19 - v0.5.2 * do not try to use USIM APDUs when initializing PC/SC for SIM card access for a network that has not enabled EAP-AKA * fixed EAP phase 2 Nak for EAP-{PEAP,TTLS,FAST} (this was broken in v0.5.1 due to the new support for expanded EAP types) * added support for generating EAP Expanded Nak * try to fetch scan results once before requesting new scan when starting up in ap_scan=1 mode (this can speed up initial association a lot with, e.g., madwifi-ng driver) * added support for receiving EAPOL frames from a Linux bridge interface (-bbr0 on command line) * fixed EAPOL re-authentication for sessions that used PMKSA caching * changed EAP method registration to use a dynamic list of methods instead of a static list generated at build time * fixed PMKSA cache deinitialization not to use freed memory when removing PMKSA entries * fixed a memory leak in EAP-TTLS re-authentication * reject WPA/WPA2 message 3/4 if it does not include any valid WPA/RSN IE * driver_wext: added fallback to use SIOCSIWENCODE for setting auth_alg if the driver does not support SIOCSIWAUTH 2006-01-29 - v0.5.1 * driver_test: added better support for multiple APs and STAs by using a directory with sockets that include MAC address for each device in the name (driver_param=test_dir=/tmp/test) * added support for EAP expanded type (vendor specific EAP methods) * added AP_SCAN command into ctrl_iface so that ap_scan configuration option can be changed if needed * wpa_cli/wpa_gui: skip non-socket files in control directory when using UNIX domain sockets; this avoids selecting an incorrect interface (e.g., a PID file could be in this directory, even though use of this directory for something else than socket files is not recommended) * fixed TLS library deinitialization after RSN pre-authentication not to disable TLS library for normal authentication * driver_wext: Remove null-termination from SSID length if the driver used it; some Linux drivers do this and they were causing problems in wpa_supplicant not finding matching configuration block. This change would break a case where the SSID actually ends in '\0', but that is not likely to happen in real use. * fixed PMKSA cache processing not to trigger deauthentication if the current PMKSA cache entry is replaced with a valid new entry * fixed PC/SC initialization for ap_scan != 1 modes (this fixes EAP-SIM and EAP-AKA with real SIM/USIM card when using ap_scan=0 or ap_scan=2) 2005-12-18 - v0.5.0 (beginning of 0.5.x development releases) * added experimental STAKey handshake implementation for IEEE 802.11e direct link setup (DLS); note: this is disabled by default in both build and runtime configuration (can be enabled with CONFIG_STAKEY=y and stakey=1) * fixed EAP-SIM and EAP-AKA pseudonym and fast re-authentication to decrypt AT_ENCR_DATA attributes correctly * fixed EAP-AKA to allow resynchronization within the same session * made code closer to ANSI C89 standard to make it easier to port to other C libraries and compilers * started moving operating system or C library specific functions into wrapper functions defined in os.h and implemented in os_*.c to make code more portable * wpa_supplicant can now be built with Microsoft Visual C++ (e.g., with the freely available Toolkit 2003 version or Visual C++ 2005 Express Edition and Platform SDK); see nmake.mak for an example makefile for nmake * added support for using Windows registry for command line parameters (CONFIG_MAIN=main_winsvc) and configuration data (CONFIG_BACKEND=winreg); see win_example.reg for an example registry contents; this version can be run both as a Windows service and as a normal application; 'wpasvc.exe app' to start as applicant, 'wpasvc.exe reg ' to register a service, 'net start wpasvc' to start the service, 'wpasvc.exe unreg' to unregister a service * made it possible to link ndis_events.exe functionality into wpa_supplicant.exe by defining CONFIG_NDIS_EVENTS_INTEGRATED * added better support for multiple control interface backends (CONFIG_CTRL_IFACE option); currently, 'unix' and 'udp' are supported * fixed PC/SC code to use correct length for GSM AUTH command buffer and to not use pioRecvPci with SCardTransmit() calls; these were not causing visible problems with pcsc-lite, but Windows Winscard.dll refused the previously used parameters; this fixes EAP-SIM and EAP-AKA authentication using SIM/USIM card under Windows * added new event loop implementation for Windows using WaitForMultipleObject() instead of select() in order to allow waiting for non-socket objects; this can be selected with CONFIG_ELOOP=eloop_win in .config * added support for selecting l2_packet implementation in .config (CONFIG_L2_PACKET; following options are available now: linux, pcap, winpcap, freebsd, none) * added new l2_packet implementation for WinPcap (CONFIG_L2_PACKET=winpcap) that uses a separate receive thread to reduce latency in EAPOL receive processing from about 100 ms to about 3 ms * added support for EAP-FAST key derivation using other ciphers than RC4-128-SHA for authentication and AES128-SHA for provisioning * added support for configuring CA certificate as DER file and as a configuration blob * fixed private key configuration as configuration blob and added support for using PKCS#12 as a blob * tls_gnutls: added support for using PKCS#12 files; added support for session resumption * added support for loading trusted CA certificates from Windows certificate store: ca_cert="cert_store://", where is likely CA (Intermediate CA certificates) or ROOT (root certificates) * added C version of ndis_events.cpp and made it possible to build this with MinGW so that CONFIG_NDIS_EVENTS_INTEGRATED can be used more easily on cross-compilation builds * added wpasvc.exe into Windows binary release; this is an alternative version of wpa_supplicant.exe with configuration backend using Windows registry and with the entry point designed to run as a Windows service * integrated ndis_events.exe functionality into wpa_supplicant.exe and wpasvc.exe and removed this additional tool from the Windows binary release since it is not needed anymore * load winscard.dll functions dynamically when building with MinGW since MinGW does not yet include winscard library 2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases) * l2_packet_pcap: fixed wired IEEE 802.1X authentication with libpcap and WinPcap to receive frames sent to PAE group address * disable EAP state machine when IEEE 802.1X authentication is not used in order to get rid of bogus "EAP failed" messages * fixed OpenSSL error reporting to go through all pending errors to avoid confusing reports of old errors being reported at later point during handshake * fixed configuration file updating to not write empty variables (e.g., proto or key_mgmt) that the file parser would not accept * fixed ADD_NETWORK ctrl_iface command to use the same default values for variables as empty network definitions read from config file would get * fixed EAP state machine to not discard EAP-Failure messages in many cases (e.g., during TLS handshake) * fixed a infinite loop in private key reading if the configured file cannot be parsed successfully * driver_madwifi: added support for madwifi-ng * wpa_gui: do not display password/PSK field contents * wpa_gui: added CA certificate configuration * driver_ndis: fixed scan request in ap_scan=2 mode not to change SSID * driver_ndis: include Beacon IEs in AssocInfo in order to notice if the new AP is using different WPA/RSN IE * use longer timeout for IEEE 802.11 association to avoid problems with drivers that may take more than five second to associate 2005-10-27 - v0.4.6 * allow fallback to WPA, if mixed WPA+WPA2 networks have mismatch in RSN IE, but WPA IE would match with wpa_supplicant configuration * added support for named configuration blobs in order to avoid having to use file system for external files (e.g., certificates); variables can be set to "blob://" instead of file path to use a named blob; supported fields: pac_file, client_cert, private_key * fixed RSN pre-authentication (it was broken in the clean up of WPA state machine interface in v0.4.5) * driver_madwifi: set IEEE80211_KEY_GROUP flag for group keys to make sure the driver configures broadcast decryption correctly * added ca_path (and ca_path2) configuration variables that can be used to configure OpenSSL CA path, e.g., /etc/ssl/certs, for using the system-wide trusted CA list * added support for starting wpa_supplicant without a configuration file (-C argument must be used to set ctrl_interface parameter for this case; in addition, -p argument can be used to provide driver_param; these new arguments can also be used with a configuration to override the values from the configuration) * added global control interface that can be optionally used for adding and removing network interfaces dynamically (-g command line argument for both wpa_supplicant and wpa_cli) without having to restart wpa_supplicant process * wpa_gui: - try to save configuration whenever something is modified - added WEP key configuration - added possibility to edit the current network configuration * driver_ndis: fixed driver polling not to increase frequency on each received EAPOL frame due to incorrectly cancelled timeout * added simple configuration file examples (in examples subdirectory) * fixed driver_wext.c to filter wireless events based on ifindex to avoid interfaces receiving events from other interfaces * delay sending initial EAPOL-Start couple of seconds to speed up authentication for the most common case of Authenticator starting EAP authentication immediately after association 2005-09-25 - v0.4.5 * added a workaround for clearing keys with ndiswrapper to allow roaming from WPA enabled AP to plaintext one * added docbook documentation (doc/docbook) that can be used to generate, e.g., man pages * l2_packet_linux: use socket type SOCK_DGRAM instead of SOCK_RAW for PF_PACKET in order to prepare for network devices that do not use Ethernet headers (e.g., network stack that includes IEEE 802.11 header in the frames) * use receipt of EAPOL-Key frame as a lower layer success indication for EAP state machine to allow recovery from dropped EAP-Success frame * cleaned up internal EAPOL frame processing by not including link layer (Ethernet) header during WPA and EAPOL/EAP processing; this header is added only when transmitted the frame; this makes it easier to use wpa_supplicant on link layers that use different header than Ethernet * updated EAP-PSK to use draft 9 by default since this can now be tested with hostapd; removed support for draft 3, including server_nai configuration option from network blocks * driver_wired: add PAE address to the multicast address list in order to be able to receive EAPOL frames with drivers that do not include these multicast addresses by default * driver_wext: add support for WE-19 * added support for multiple configuration backends (CONFIG_BACKEND option); currently, only 'file' is supported (i.e., the format used in wpa_supplicant.conf) * added support for updating configuration ('wpa_cli save_config'); this is disabled by default and can be enabled with global update_config=1 variable in wpa_supplicant.conf; this allows wpa_cli and wpa_gui to store the configuration changes in a permanent store * added GET_NETWORK ctrl_iface command (e.g., 'wpa_cli get_network 0 ssid') 2005-08-21 - v0.4.4 * replaced OpenSSL patch for EAP-FAST support (openssl-tls-extensions.patch) with a more generic and correct patch (the new patch is not compatible with the previous one, so the OpenSSL library will need to be patched with the new patch in order to be able to build wpa_supplicant with EAP-FAST support) * added support for using Windows certificate store (through CryptoAPI) for client certificate and private key operations (EAP-TLS) (see wpa_supplicant.conf for more information on how to configure this with private_key) * ported wpa_gui to Windows * added Qt4 version of wpa_gui (wpa_gui-qt4 directory); this can be built with the open source version of the Qt4 for Windows * allow non-WPA modes (e.g., IEEE 802.1X with dynamic WEP) to be used with drivers that do not support WPA * ndis_events: fixed Windows 2000 support * added support for enabling/disabling networks from the list of all configured networks ('wpa_cli enable_network ' and 'wpa_cli disable_network ') * added support for adding and removing network from the current configuration ('wpa_cli add_network' and 'wpa_cli remove_network '); added networks are disabled by default and they can be enabled with enable_network command once the configuration is done for the new network; note: configuration file is not yet updated, so these new networks are lost when wpa_supplicant is restarted * added support for setting network configuration parameters through the control interface, for example: wpa_cli set_network 0 ssid "\"my network\"" * fixed parsing of strings that include both " and # within double quoted area (e.g., "start"#end") * added EAP workaround for PEAP session resumption: allow outer, i.e., not tunneled, EAP-Success to terminate session since; this can be disabled with eap_workaround=0 (this was allowed for PEAPv1 before, but now it is also allowed for PEAPv0 since at least one RADIUS authentication server seems to be doing this for PEAPv0, too) * wpa_gui: added preliminary support for adding new networks to the wpa_supplicant configuration (double click on the scan results to open network configuration) 2005-06-26 - v0.4.3 * removed interface for external EAPOL/EAP supplicant (e.g., Xsupplicant), (CONFIG_XSUPPLICANT_IFACE) since it is not required anymore and is unlikely to be used by anyone * driver_ndis: fixed WinPcap 3.0 support * fixed build with CONFIG_DNET_PCAP=y on Linux * l2_packet: moved different implementations into separate files (l2_packet_*.c) 2005-06-12 - v0.4.2 * driver_ipw: updated driver structures to match with ipw2200-1.0.4 (note: ipw2100-1.1.0 is likely to require an update to work with this) * added support for using ap_scan=2 mode with multiple network blocks; wpa_supplicant will go through the networks one by one until the driver reports a successful association; this uses the same order for networks as scan_ssid=1 scans, i.e., the priority field is ignored and the network block order in the file is used instead * fixed a potential issue in RSN pre-authentication ending up using freed memory if pre-authentication times out * added support for matching alternative subject name extensions of the authentication server certificate; new configuration variables altsubject_match and altsubject_match2 * driver_ndis: added support for IEEE 802.1X authentication with wired NDIS drivers * added support for querying private key password (EAP-TLS) through the control interface (wpa_cli/wpa_gui) if one is not included in the configuration file * driver_broadcom: fixed couple of memory leaks in scan result processing * EAP-PAX is now registered as EAP type 46 * fixed EAP-PAX MAC calculation * fixed EAP-PAX CK and ICK key derivation * added support for using password with EAP-PAX (as an alternative to entering key with eappsk); SHA-1 hash of the password will be used as the key in this case * added support for arbitrary driver interface parameters through the configuration file with a new driver_param field; this adds a new driver_ops function set_param() * added possibility to override l2_packet module with driver interface API (new send_eapol handler); this can be used to implement driver specific TX/RX functions for EAPOL frames * fixed ctrl_interface_group processing for the case where gid is entered as a number, not group name * driver_test: added support for testing hostapd with wpa_supplicant by using test driver interface without any kernel drivers or network cards 2005-05-22 - v0.4.1 * driver_madwifi: fixed WPA/WPA2 mode configuration to allow EAPOL packets to be encrypted; this was apparently broken by the changed ioctl order in v0.4.0 * driver_madwifi: added preliminary support for compiling against 'BSD' branch of madwifi CVS tree * added support for EAP-MSCHAPv2 password retries within the same EAP authentication session * added support for password changes with EAP-MSCHAPv2 (used when the password has expired) * added support for reading additional certificates from PKCS#12 files and adding them to the certificate chain * fixed association with IEEE 802.1X (no WPA) when dynamic WEP keys were used * fixed a possible double free in EAP-TTLS fast-reauthentication when identity or password is entered through control interface * display EAP Notification messages to user through control interface with "CTRL-EVENT-EAP-NOTIFICATION" prefix * added GUI version of wpa_cli, wpa_gui; this is not build automatically with 'make'; use 'make wpa_gui' to build (this requires Qt development tools) * added 'disconnect' command to control interface for setting wpa_supplicant in state where it will not associate before 'reassociate' command has been used * added support for selecting a network from the list of all configured networks ('wpa_cli select_network '; this disabled all other networks; to re-enable, 'wpa_cli select_network any') * added support for getting scan results through control interface * added EAP workaround for PEAPv1 session resumption: allow outer, i.e., not tunneled, EAP-Success to terminate session since; this can be disabled with eap_workaround=0 2005-04-25 - v0.4.0 (beginning of 0.4.x development releases) * added a new build time option, CONFIG_NO_STDOUT_DEBUG, that can be used to reduce the size of the wpa_supplicant considerably if debugging code is not needed * fixed EAPOL-Key validation to drop packets with invalid Key Data Length; such frames could have crashed wpa_supplicant due to buffer overflow * added support for wired authentication (IEEE 802.1X on wired Ethernet); driver interface 'wired' * obsoleted set_wpa() handler in the driver interface API (it can be replaced by moving enable/disable functionality into init()/deinit()) (calls to set_wpa() are still present for backwards compatibility, but they may be removed in the future) * driver_madwifi: fixed association in plaintext mode * modified the EAP workaround that accepts EAP-Success with incorrect Identifier to be even less strict about verification in order to interoperate with some authentication servers * added support for sending TLS alerts * added support for 'any' SSID wildcard; if ssid is not configured or is set to an empty string, any SSID will be accepted for non-WPA AP * added support for asking PIN (for SIM) from frontends (e.g., wpa_cli); if a PIN is needed, but not included in the configuration file, a control interface request is sent and EAP processing is delayed until the PIN is available * added support for using external devices (e.g., a smartcard) for private key operations in EAP-TLS (CONFIG_SMARTCARD=y in .config); new wpa_supplicant.conf variables: - global: opensc_engine_path, pkcs11_engine_path, pkcs11_module_path - network: engine, engine_id, key_id * added experimental support for EAP-PAX * added monitor mode for wpa_cli (-a) that allows external commands (e.g., shell scripts) to be run based on wpa_supplicant events, e.g., when authentication has been completed and data connection is ready; other related wpa_cli arguments: -B (run in background), -P (write PID file); wpa_supplicant has a new command line argument (-W) that can be used to make it wait until a control interface command is received in order to avoid missing events * added support for opportunistic WPA2 PMKSA key caching (disabled by default, can be enabled with proactive_key_caching=1) * fixed RSN IE in 4-Way Handshake message 2/4 for the case where Authenticator rejects PMKSA caching attempt and the driver is not using assoc_info events * added -P argument for wpa_supplicant to write the current process id into a file 2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) * added new phase1 option parameter, include_tls_length=1, to force wpa_supplicant to add TLS Message Length field to all TLS messages even if the packet is not fragmented; this may be needed with some authentication servers * fixed WPA/RSN IE verification in message 3 of 4-Way Handshake when using drivers that take care of AP selection (e.g., when using ap_scan=2) * fixed reprocessing of pending request after ctrl_iface requests for identity/password/otp * fixed ctrl_iface requests for identity/password/otp in Phase 2 of EAP-PEAP and EAP-TTLS * all drivers using driver_wext: set interface up and select Managed mode when starting wpa_supplicant; set interface down when exiting * renamed driver_ipw2100.c to driver_ipw.c since it now supports both ipw2100 and ipw2200; please note that this also changed the configuration variable in .config to CONFIG_DRIVER_IPW 2005-01-24 - v0.3.6 * fixed a busy loop introduced in v0.3.5 for scan result processing when no matching AP is found 2005-01-23 - v0.3.5 * added a workaround for an interoperability issue with a Cisco AP when using WPA2-PSK * fixed non-WPA IEEE 802.1X to use the same authentication timeout as WPA with IEEE 802.1X (i.e., timeout 10 -> 70 sec to allow retransmission of dropped frames) * fixed issues with 64-bit CPUs and SHA1 cleanup in previous version (e.g., segfault when processing EAPOL-Key frames) * fixed EAP workaround and fast reauthentication configuration for RSN pre-authentication; previously these were disabled and pre-authentication would fail if the used authentication server requires EAP workarounds * added support for blacklisting APs that fail or timeout authentication in ap_scan=1 mode so that all APs are tried in cases where the ones with strongest signal level are failing authentication * fixed CA certificate loading after a failed EAP-TLS/PEAP/TTLS authentication attempt * allow EAP-PEAP/TTLS fast reauthentication only if Phase 2 succeeded in the previous authentication (previously, only Phase 1 success was verified) 2005-01-09 - v0.3.4 * added preliminary support for IBSS (ad-hoc) mode configuration (mode=1 in network block); this included a new key_mgmt mode WPA-NONE, i.e., TKIP or CCMP with a fixed key (based on psk) and no key management; see wpa_supplicant.conf for more details and an example on how to configure this (note: this is currently implemented only for driver_hostapd.c, but the changes should be trivial to add in associate() handler for other drivers, too (assuming the driver supports WPA-None) * added preliminary port for native Windows (i.e., no cygwin) using mingw 2005-01-02 - v0.3.3 * added optional support for GNU Readline and History Libraries for wpa_cli (CONFIG_READLINE) * cleaned up EAP state machine <-> method interface and number of small problems with error case processing not terminating on EAP-Failure but waiting for timeout * added couple of workarounds for interoperability issues with a Cisco AP when using WPA2 * added support for EAP-FAST (draft-cam-winget-eap-fast-00.txt); Note: This requires a patch for openssl to add support for TLS extensions and number of workarounds for operations without certificates. Proof of concept type of experimental patch is included in openssl-tls-extensions.patch. 2004-12-19 - v0.3.2 * fixed private key loading for cases where passphrase is not set * fixed Windows/cygwin L2 packet handler freeing; previous version could cause a segfault when RSN pre-authentication was completed * added support for PMKSA caching with drivers that generate RSN IEs (e.g., NDIS); currently, this is only implemented in driver_ndis.c, but similar code can be easily added to driver_ndiswrapper.c once ndiswrapper gets full support for RSN PMKSA caching * improved recovery from PMKID mismatches by requesting full EAP authentication in case of failed PMKSA caching attempt * driver_ndis: added support for NDIS NdisMIncidateStatus() events (this requires that ndis_events is ran while wpa_supplicant is running) * driver_ndis: use ADD_WEP/REMOVE_WEP when configuring WEP keys * added support for driver interfaces to replace the interface name based on driver/OS specific mapping, e.g., in case of driver_ndis, this allows the beginning of the adapter description to be used as the interface name * added support for CR+LF (Windows-style) line ends in configuration file * driver_ndis: enable radio before starting scanning, disable radio when exiting * modified association event handler to set portEnabled = FALSE before clearing port Valid in order to reset EAP state machine and avoid problems with new authentication getting ignored because of state machines ending up in AUTHENTICATED/SUCCESS state based on old information * added support for driver events to add PMKID candidates in order to allow drivers to give priority to most likely roaming candidates * driver_hostap: moved PrivacyInvoked configuration to associate() function so that this will not be set for plaintext connections * added KEY_MGMT_802_1X_NO_WPA as a new key_mgmt type so that driver interface can distinguish plaintext and IEEE 802.1X (no WPA) authentication * fixed static WEP key configuration to use broadcast/default type for all keys (previously, the default TX key was configured as pairwise/ unicast key) * driver_ndis: added legacy WPA capability detection for non-WPA2 drivers * added support for setting static WEP keys for IEEE 802.1X without dynamic WEP keying (eapol_flags=0) 2004-12-12 - v0.3.1 * added support for reading PKCS#12 (PFX) files (as a replacement for PEM/DER) to get certificate and private key (CONFIG_PKCS12) * fixed compilation with CONFIG_PCSC=y * added new ap_scan mode, ap_scan=2, for drivers that take care of association, but need to be configured with security policy and SSID, e.g., ndiswrapper and NDIS driver; this mode should allow such drivers to work with hidden SSIDs and optimized roaming; when ap_scan=2 is used, only the first network block in the configuration file is used and this configuration should have explicit security policy (i.e., only one option in the lists) for key_mgmt, pairwise, group, proto variables * added experimental port of wpa_supplicant for Windows - driver_ndis.c driver interface (NDIS OIDs) - currently, this requires cygwin and WinPcap - small utility, win_if_list, can be used to get interface name * control interface can now be removed at build time; add CONFIG_CTRL_IFACE=y to .config to maintain old functionality * optional Xsupplicant interface can now be removed at build time; (CONFIG_XSUPPLICANT_IFACE=y in .config to bring it back) * added auth_alg to driver interface associate() parameters to make it easier for drivers to configure authentication algorithm as part of the association 2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) * driver_broadcom: added new driver interface for Broadcom wl.o driver (a generic driver for Broadcom IEEE 802.11a/g cards) * wpa_cli: fixed parsing of -p command line argument * PEAPv1: fixed tunneled EAP-Success reply handling to reply with TLS ACK, not tunneled EAP-Success (of which only the first byte was actually send due to a bug in previous code); this seems to interoperate with most RADIUS servers that implements PEAPv1 * PEAPv1: added support for terminating PEAP authentication on tunneled EAP-Success message; this can be configured by adding peap_outer_success=0 on phase1 parameters in wpa_supplicant.conf (some RADIUS servers require this whereas others require a tunneled reply * PEAPv1: changed phase1 option peaplabel to use default to 0, i.e., to the old label for key derivation; previously, the default was 1, but it looks like most existing PEAPv1 implementations use the old label which is thus more suitable default option * added support for EAP-PSK (draft-bersani-eap-psk-03.txt) * fixed parsing of wep_tx_keyidx * added support for configuring list of allowed Phase 2 EAP types (for both EAP-PEAP and EAP-TTLS) instead of only one type * added support for configuring IEEE 802.11 authentication algorithm (auth_alg; mainly for using Shared Key authentication with static WEP keys) * added support for EAP-AKA (with UMTS SIM) * fixed couple of errors in PCSC handling that could have caused random-looking errors for EAP-SIM * added support for EAP-SIM pseudonyms and fast re-authentication * added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS session resumption) * added support for EAP-SIM with two challenges (phase1="sim_min_num_chal=3" can be used to require three challenges) * added support for configuring DH/DSA parameters for an ephemeral DH key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters dh_file and dh_file2 (phase 2); this adds support for using DSA keys and optional DH key exchange to achieve forward secracy with RSA keys * added support for matching subject of the authentication server certificate with a substring when using EAP-TLS/PEAP/TTLS; new configuration variables subject_match and subject_match2 * changed SSID configuration in driver_wext.c (used by many driver interfaces) to use ssid_len+1 as the length for SSID since some Linux drivers expect this * fixed couple of unaligned reads in scan result parsing to fix WPA connection on some platforms (e.g., ARM) * added driver interface for Intel ipw2100 driver * added support for LEAP with WPA * added support for larger scan results report (old limit was 4 kB of data, i.e., about 35 or so APs) when using Linux wireless extensions v17 or newer * fixed a bug in PMKSA cache processing: skip sending of EAPOL-Start only if there is a PMKSA cache entry for the current AP * fixed error handling for case where reading of scan results fails: must schedule a new scan or wpa_supplicant will remain waiting forever * changed debug output to remove shared password/key material by default; all key information can be included with -K command line argument to match the previous behavior * added support for timestamping debug log messages (disabled by default, can be enabled with -t command line argument) * set pairwise/group cipher suite for non-WPA IEEE 802.1X to WEP-104 if keys are not configured to be used; this fixes IEEE 802.1X mode with drivers that use this information to configure whether Privacy bit can be in Beacon frames (e.g., ndiswrapper) * avoid clearing driver keys if no keys have been configured since last key clear request; this seems to improve reliability of group key handshake for ndiswrapper & NDIS driver which seems to be suffering of some kind of timing issue when the keys are cleared again after association * changed driver interface API: - WPA_SUPPLICANT_DRIVER_VERSION define can be used to determine which version is being used (now, this is set to 2; previously, it was not defined) - pass pointer to private data structure to all calls - the new API is not backwards compatible; all in-tree driver interfaces has been converted to the new API * added support for controlling multiple interfaces (radios) per wpa_supplicant process; each interface needs to be listed on the command line (-c, -i, -D arguments) with -N as a separator (-cwpa1.conf -iwlan0 -Dhostap -N -cwpa2.conf -iath0 -Dmadwifi) * added a workaround for EAP servers that incorrectly use same Id for sequential EAP packets * changed libpcap/libdnet configuration to use .config variable, CONFIG_DNET_PCAP, instead of requiring Makefile modification * improved downgrade attack detection in IE verification of msg 3/4: verify both WPA and RSN IEs, if present, not only the selected one; reject the AP if an RSN IE is found in msg 3/4, but not in Beacon or Probe Response frame, and RSN is enabled in wpa_supplicant configuration * fixed WPA msg 3/4 processing to allow Key Data field contain other IEs than just one WPA IE * added support for FreeBSD and driver interface for the BSD net80211 layer (CONFIG_DRIVER_BSD=y in .config); please note that some of the required kernel mods have not yet been committed * made EAP workarounds configurable; enabled by default, can be disabled with network block option eap_workaround=0 2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) * resolved couple of interoperability issues with EAP-PEAPv1 and Phase 2 (inner EAP) fragment reassembly * driver_madwifi: fixed WEP key configuration for IEEE 802.1X when the AP is using non-zero key index for the unicast key and key index zero for the broadcast key * driver_hostap: fixed IEEE 802.1X WEP key updates and re-authentication by allowing unencrypted EAPOL frames when not using WPA * added a new driver interface, 'wext', which uses only standard, driver independent functionality in Linux wireless extensions; currently, this can be used only for non-WPA IEEE 802.1X mode, but eventually, this is to be extended to support full WPA/WPA2 once Linux wireless extensions get support for this * added support for mode in which the driver is responsible for AP scanning and selection; this is disabled by default and can be enabled with global ap_scan=0 variable in wpa_supplicant.conf; this mode can be used, e.g., with generic 'wext' driver interface to use wpa_supplicant as IEEE 802.1X Supplicant with any Linux driver supporting wireless extensions. * driver_madwifi: fixed WPA2 configuration and scan_ssid=1 (e.g., operation with an AP that does not include SSID in the Beacon frames) * added support for new EAP authentication methods: EAP-TTLS/EAP-OTP, EAP-PEAPv0/OTP, EAP-PEAPv1/OTP, EAP-OTP * added support for asking one-time-passwords from frontends (e.g., wpa_cli); this 'otp' command works otherwise like 'password' command, but the password is used only once and the frontend will be asked for a new password whenever a request from authenticator requires a password; this can be used with both EAP-OTP and EAP-GTC * changed wpa_cli to automatically re-establish connection so that it does not need to be re-started when wpa_supplicant is terminated and started again * improved user data (identity/password/otp) requests through frontends: process pending EAPOL packets after getting new information so that full authentication does not need to be restarted; in addition, send pending requests again whenever a new frontend is attached * changed control frontends to use a new directory for socket files to make it easier for wpa_cli to automatically select between interfaces and to provide access control for the control interface; wpa_supplicant.conf: ctrl_interface is now a path (/var/run/wpa_supplicant is the recommended path) and ctrl_interface_group can be used to select which group gets access to the control interface; wpa_cli: by default, try to connect to the first interface available in /var/run/wpa_supplicant; this path can be overridden with -p option and an interface can be selected with -i option (i.e., in most common cases, wpa_cli does not need to get any arguments) * added support for LEAP * added driver interface for Linux ndiswrapper * added priority option for network blocks in the configuration file; this allows networks to be grouped based on priority (the scan results are searched for matches with network blocks in this order) 2004-06-20 - v0.2.3 * sort scan results to improve AP selection * fixed control interface socket removal for some error cases * improved scan requesting and authentication timeout * small improvements/bug fixes for EAP-MSCHAPv2, EAP-PEAP, and TLS processing * PEAP version can now be forced with phase1="peapver=" (mostly for testing; by default, the highest version supported by both the Supplicant and Authentication Server is selected automatically) * added support for madwifi driver (Atheros ar521x) * added a workaround for cases where AP sets Install Tx/Rx bit for WPA Group Key messages when pairwise keys are used (without this, the Group Key would be used for Tx and the AP would drop frames from the station) * added GSM SIM/USIM interface for GSM authentication algorithm for EAP-SIM; this requires pcsc-lite * added support for ATMEL AT76C5XXx driver * fixed IEEE 802.1X WEP key derivation in the case where Authenticator does not include key data in the EAPOL-Key frame (i.e., part of EAP keying material is used as data encryption key) * added support for using plaintext and static WEP networks (key_mgmt=NONE) 2004-05-31 - v0.2.2 * added support for new EAP authentication methods: EAP-TTLS/EAP-MD5-Challenge EAP-TTLS/EAP-GTC EAP-TTLS/EAP-MSCHAPv2 EAP-TTLS/EAP-TLS EAP-TTLS/MSCHAPv2 EAP-TTLS/MSCHAP EAP-TTLS/PAP EAP-TTLS/CHAP EAP-PEAP/TLS EAP-PEAP/GTC EAP-PEAP/MD5-Challenge EAP-GTC EAP-SIM (not yet complete; needs GSM/SIM authentication interface) * added support for anonymous identity (to be used when identity is sent in plaintext; real identity will be used within TLS protected tunnel (e.g., with EAP-TTLS) * added event messages from wpa_supplicant to frontends, e.g., wpa_cli * added support for requesting identity and password information using control interface; in other words, the password for EAP-PEAP or EAP-TTLS does not need to be included in the configuration file since a frontand (e.g., wpa_cli) can ask it from the user * improved RSN pre-authentication to use a candidate list and process all candidates from each scan; not only one per scan * fixed RSN IE and WPA IE capabilities field parsing * ignore Tx bit in GTK IE when Pairwise keys are used * avoid making new scan requests during IEEE 802.1X negotiation * use openssl/libcrypto for MD5 and SHA-1 when compiling wpa_supplicant with TLS support (this replaces the included implementation with library code to save about 8 kB since the library code is needed anyway for TLS) * fixed WPA-PSK only mode when compiled without IEEE 802.1X support (i.e., without CONFIG_IEEE8021X_EAPOL=y in .config) 2004-05-06 - v0.2.1 * added support for internal IEEE 802.1X (actually, IEEE 802.1aa/D6.1) Supplicant - EAPOL state machines for Supplicant [IEEE 802.1aa/D6.1] - EAP peer state machine [draft-ietf-eap-statemachine-02.pdf] - EAP-MD5 (cannot be used with WPA-RADIUS) [draft-ietf-eap-rfc2284bis-09.txt] - EAP-TLS [RFC 2716] - EAP-MSCHAPv2 (currently used only with EAP-PEAP) - EAP-PEAP/MSCHAPv2 [draft-josefsson-pppext-eap-tls-eap-07.txt] [draft-kamath-pppext-eap-mschapv2-00.txt] (PEAP version 0, 1, and parts of 2; only 0 and 1 are enabled by default; tested with FreeRADIUS, Microsoft IAS, and Funk Odyssey) - new configuration file options: eap, identity, password, ca_cert, client_cert, privatekey, private_key_passwd - Xsupplicant is not required anymore, but it can be used by disabling the internal IEEE 802.1X Supplicant with -e command line option - this code is not included in the default build; Makefile need to be edited for this (uncomment lines for selected functionality) - EAP-TLS and EAP-PEAP require openssl libraries * use module prefix in debug messages (WPA, EAP, EAP-TLS, ..) * added support for non-WPA IEEE 802.1X mode with dynamic WEP keys (i.e., complete IEEE 802.1X/EAP authentication and use IEEE 802.1X EAPOL-Key frames instead of WPA key handshakes) * added support for IEEE 802.11i/RSN (WPA2) - improved PTK Key Handshake - PMKSA caching, pre-authentication * fixed wpa_supplicant to ignore possible extra data after WPA EAPOL-Key packets (this fixes 'Invalid EAPOL-Key MIC when using TPTK' error from message 3 of 4-Way Handshake in case the AP includes extra data after the EAPOL-Key) * added interface for external programs (frontends) to control wpa_supplicant - CLI example (wpa_cli) with interactive mode and command line mode - replaced SIGUSR1 status/statistics with the new control interface * made some feature compile time configurable - .config file for make - driver interfaces (hostap, hermes, ..) - EAPOL/EAP functions 2004-02-15 - v0.2.0 * Initial version of wpa_supplicant diff --git a/contrib/wpa/wpa_supplicant/README b/contrib/wpa/wpa_supplicant/README index 05f15ff46bda..c643b2684700 100644 --- a/contrib/wpa/wpa_supplicant/README +++ b/contrib/wpa/wpa_supplicant/README @@ -1,1163 +1,1163 @@ wpa_supplicant ============== -Copyright (c) 2003-2019, Jouni Malinen and contributors +Copyright (c) 2003-2022, Jouni Malinen and contributors All Rights Reserved. This program is licensed under the BSD license (the one with advertisement clause removed). If you are submitting changes to the project, please see CONTRIBUTIONS file for more instructions. License ------- This software may be distributed, used, and modified under the terms of BSD license: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name(s) of the above-listed copyright holder(s) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Features -------- Supported WPA/IEEE 802.11i features: - WPA-PSK ("WPA-Personal") - WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") Following authentication methods are supported with an integrate IEEE 802.1X Supplicant: * EAP-TLS * EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1) * EAP-PEAP/TLS (both PEAPv0 and PEAPv1) * EAP-PEAP/GTC (both PEAPv0 and PEAPv1) * EAP-PEAP/OTP (both PEAPv0 and PEAPv1) * EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1) * EAP-TTLS/EAP-MD5-Challenge * EAP-TTLS/EAP-GTC * EAP-TTLS/EAP-OTP * EAP-TTLS/EAP-MSCHAPv2 * EAP-TTLS/EAP-TLS * EAP-TTLS/MSCHAPv2 * EAP-TTLS/MSCHAP * EAP-TTLS/PAP * EAP-TTLS/CHAP * EAP-SIM * EAP-AKA * EAP-AKA' * EAP-PSK * EAP-PAX * EAP-SAKE * EAP-IKEv2 * EAP-GPSK * EAP-pwd * LEAP (note: requires special support from the driver for IEEE 802.11 authentication) (following methods are supported, but since they do not generate keying material, they cannot be used with WPA or IEEE 802.1X WEP keying) * EAP-MD5-Challenge * EAP-MSCHAPv2 * EAP-GTC * EAP-OTP - key management for CCMP, TKIP, WEP104, WEP40 - RSN/WPA2 (IEEE 802.11i) * pre-authentication * PMKSA caching Supported TLS/crypto libraries: - OpenSSL (default) - GnuTLS Internal TLS/crypto implementation (optional): - can be used in place of an external TLS/crypto library - TLSv1 - X.509 certificate processing - PKCS #1 - ASN.1 - RSA - bignum - minimal size (ca. 50 kB binary, parts of which are already needed for WPA; TLSv1/X.509/ASN.1/RSA/bignum parts are about 25 kB on x86) Requirements ------------ Current hardware/software requirements: - Linux kernel 2.4.x or 2.6.x with Linux Wireless Extensions v15 or newer - FreeBSD 6-CURRENT - NetBSD-current - Microsoft Windows with WinPcap (at least WinXP, may work with other versions) - drivers: Linux drivers that support cfg80211/nl80211. Even though there are number of driver specific interface included in wpa_supplicant, please note that Linux drivers are moving to use generic wireless configuration interface driver_nl80211 (-Dnl80211 on wpa_supplicant command line) should be the default option to start with before falling back to driver specific interface. Linux drivers that support WPA/WPA2 configuration with the generic Linux wireless extensions (WE-18 or newer). Obsoleted by nl80211. In theory, any driver that supports Linux wireless extensions can be used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in configuration file. Wired Ethernet drivers (with ap_scan=0) BSD net80211 layer (e.g., Atheros driver) At the moment, this is for FreeBSD 6-CURRENT branch and NetBSD-current. Windows NDIS The current Windows port requires WinPcap (http://winpcap.polito.it/). See README-Windows.txt for more information. wpa_supplicant was designed to be portable for different drivers and operating systems. Hopefully, support for more wlan cards and OSes will be added in the future. See developer's documentation (http://hostap.epitest.fi/wpa_supplicant/devel/) for more information about the design of wpa_supplicant and porting to other drivers. One main goal is to add full WPA/WPA2 support to Linux wireless extensions to allow new drivers to be supported without having to implement new driver-specific interface code in wpa_supplicant. Optional libraries for layer2 packet processing: - libpcap (tested with 0.7.2, most relatively recent versions assumed to work, this is likely to be available with most distributions, http://tcpdump.org/) - libdnet (tested with v1.4, most versions assumed to work, http://libdnet.sourceforge.net/) These libraries are _not_ used in the default Linux build. Instead, internal Linux specific implementation is used. libpcap/libdnet are more portable and they can be used by adding CONFIG_L2_PACKET=pcap into .config. They may also be selected automatically for other operating systems. In case of Windows builds, WinPcap is used by default (CONFIG_L2_PACKET=winpcap). Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS: - OpenSSL (tested with 1.0.1 and 1.0.2 versions; assumed to work with most relatively recent versions; this is likely to be available with most distributions, http://www.openssl.org/) - GnuTLS - internal TLSv1 implementation One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP implementation. A configuration file, .config, for compilation is needed to enable IEEE 802.1X/EAPOL and EAP methods. Note that EAP-MD5, EAP-GTC, EAP-OTP, and EAP-MSCHAPV2 cannot be used alone with WPA, so they should only be enabled if testing the EAPOL/EAP state machines. However, there can be used as inner authentication algorithms with EAP-PEAP and EAP-TTLS. See Building and installing section below for more detailed information about the wpa_supplicant build time configuration. WPA --- The original security mechanism of IEEE 802.11 standard was not designed to be strong and has proven to be insufficient for most networks that require some kind of security. Task group I (Security) of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked to address the flaws of the base standard and has in practice completed its work in May 2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was approved in June 2004 and published in July 2004. Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the IEEE 802.11i work (draft 3.0) to define a subset of the security enhancements that can be implemented with existing wlan hardware. This is called Wi-Fi Protected Access (WPA). This has now become a mandatory component of interoperability testing and certification done by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web site (http://www.wi-fi.org/OpenSection/protected_access.asp). IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm for protecting wireless networks. WEP uses RC4 with 40-bit keys, 24-bit initialization vector (IV), and CRC32 to protect against packet forgery. All these choices have proven to be insufficient: key space is too small against current attacks, RC4 key scheduling is insufficient (beginning of the pseudorandom stream should be skipped), IV space is too small and IV reuse makes attacks easier, there is no replay protection, and non-keyed authentication does not protect against bit flipping packet data. WPA is an intermediate solution for the security issues. It uses Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a compromise on strong security and possibility to use existing hardware. It still uses RC4 for the encryption like WEP, but with per-packet RC4 keys. In addition, it implements replay protection, keyed packet authentication mechanism (Michael MIC). Keys can be managed using two different mechanisms. WPA can either use an external authentication server (e.g., RADIUS) and EAP just like IEEE 802.1X is using or pre-shared keys without need for additional servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal", respectively. Both mechanisms will generate a master session key for the Authenticator (AP) and Supplicant (client station). WPA implements a new key handshake (4-Way Handshake and Group Key Handshake) for generating and exchanging data encryption keys between the Authenticator and Supplicant. This handshake is also used to verify that both Authenticator and Supplicant know the master session key. These handshakes are identical regardless of the selected key management mechanism (only the method for generating master session key changes). IEEE 802.11i / WPA2 ------------------- The design for parts of IEEE 802.11i that were not included in WPA has finished (May 2004) and this amendment to IEEE 802.11 was approved in June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new version of WPA called WPA2. This includes, e.g., support for more robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC) to replace TKIP and optimizations for handoff (reduced number of messages in initial key handshake, pre-authentication, and PMKSA caching). wpa_supplicant -------------- wpa_supplicant is an implementation of the WPA Supplicant component, i.e., the part that runs in the client stations. It implements WPA key negotiation with a WPA Authenticator and EAP authentication with Authentication Server. In addition, it controls the roaming and IEEE 802.11 authentication/association of the wlan driver. wpa_supplicant is designed to be a "daemon" program that runs in the background and acts as the backend component controlling the wireless connection. wpa_supplicant supports separate frontend programs and an example text-based frontend, wpa_cli, is included with wpa_supplicant. Following steps are used when associating with an AP using WPA: - wpa_supplicant requests the kernel driver to scan neighboring BSSes - wpa_supplicant selects a BSS based on its configuration - wpa_supplicant requests the kernel driver to associate with the chosen BSS - If WPA-EAP: integrated IEEE 802.1X Supplicant completes EAP authentication with the authentication server (proxied by the Authenticator in the AP) - If WPA-EAP: master key is received from the IEEE 802.1X Supplicant - If WPA-PSK: wpa_supplicant uses PSK as the master session key - wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake with the Authenticator (AP) - wpa_supplicant configures encryption keys for unicast and broadcast - normal data packets can be transmitted and received Building and installing ----------------------- In order to be able to build wpa_supplicant, you will first need to select which parts of it will be included. This is done by creating a build time configuration file, .config, in the wpa_supplicant root directory. Configuration options are text lines using following format: CONFIG_